Python,dataframe:根据列表中的项目数复制行并对结果行进行排名

时间:2017-03-03 14:46:41

标签: python list pandas dataframe

我的python脚本的输出是一个pandas数据帧,如下所示:

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 个答案:

答案 0 :(得分: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())))

答案 1 :(得分: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它也适用于具有多列的通用DataFrame