2017-03-03 1 views
2

Ich habe als eine Ausgabe meiner Python-Skript ein Pandas Datenrahmen wie folgt:Python, Datenrahmen: Duplizierung Reihen nach der Anzahl der Elemente in einer Liste und Reihung der Folge Reihen

id1   id_list 
1   [10,11,12] 
2   [14,15,16]  
3   [17,18,19] 

Ich möchte duplizieren Zeilen zu so viel wie Elemente, die id_list enthält, und jedem Element in dieser Liste einen Rang zuweisen, der seiner Position in der Liste entspricht.

Der Ausgang ich suche ist wie folgt:

id1   id2   rank 
1   10    1  
1   11    2 
1   12    3 
2   14    1 
2   15    2 
2   16    3 
3   17    1 
3   18    2 
3   19    3 

Dank für Ihre Hilfe danken.

Antwort

2

Sie müssen den Datenrahmen mit numpy.repeat neu zu erstellen, während die Liste Spalten gleichzeitig die Abflachung:

import numpy as np 
from itertools import chain 
pd.DataFrame({'id1': np.repeat(df.id1.values, df.id_list.str.len()), 
       'id_list': list(chain.from_iterable(df.id_list)), 
       'rank': [i for r in df.id_list for i, _ in enumerate(r, start=1)]}) 

# id1 id_list rank 
#0 1  10 1 
#0 1  11 2 
#0 1  12 3 
#1 2  14 1 
#1 2  15 2 
#1 2  16 3 
#2 3  17 1 
#2 3  18 2 
#2 3  19 3 

Oder vielleicht etwas effizienter:

import numpy as np 

(pd.DataFrame([iv for r in df.id_list for iv in enumerate(r, start=1)], 
       columns=['id_list', 'rank']) 
.assign(id1 = np.repeat(df.id1.values, df.id_list.str.len()))) 
+0

Die zweite funktioniert perfekt, danke. Der erste ist gut, aber er dupliziert auch die Indizes, er inkrementiert sie nicht. – Amy21

+0

Ich habe die erste Option so modifiziert, dass sie eindeutige Indizes gibt, das sollte jetzt auch funktionieren. – Psidom

+0

wow, sehr schöne Lösung! – MaxU

1

Hier ist meine Lösung:

In [176]: lst_col = 'id_list' 

In [177]: pd.DataFrame({ 
    ...:  col:np.repeat(df[col].values, df[lst_col].str.len()) 
    ...:  for col in df.columns.difference([lst_col]) 
    ...: }).assign(**{lst_col:np.concatenate(df[lst_col].values)}) \ 
    ...: .assign(rank=[i+1 for l in df[lst_col].str.len() for i in range(l)]) 
Out[177]: 
    id1 id_list rank 
0 1  10  1 
1 1  11  2 
2 1  12  3 
3 2  14  1 
4 2  15  2 
5 2  16  3 
6 3  17  1 
7 3  18  2 
8 3  19  3 

PS sollte es auch für generische DataFrames mit mehreren Spalten funktionieren s

Verwandte Themen