2017-03-03 6 views
2

た行をリスト内の項目の数に応じてランク付け:Pythonの、データフレーム:複製行以下のように私はPythonスクリプトの出力としてパンダのデータフレームを持って

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

私は複製したいですid_listに含まれる行数分の行をリスト内の位置に対応するランクをそのリスト内のすべての項目に属性付けします。

次のように私が探しています出力は、次のとおりです。

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 

あなたの助けをいただき、ありがとうございます。

答えて

2

同時にリストの列を平坦化しながら、あなたはnumpy.repeatとデータフレームを再構築する必要があります。

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 

それとも、もう少し効率的な:ここで

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

2つ目は完全に動作します。ありがとうございます。最初のものは良いですが、インデックスも重複していますが、増分しません。 – Amy21

+0

一意のインデックスを与えるように最初のオプションを変更しましたが、今でもうまくいくはずです。 – Psidom

+0

うわー、とても素敵な解決策! – MaxU

1

は私のソリューションです:

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複数の列を持つ汎用のDataFramesでも動作するはずですs

関連する問題