【问题标题】:Python, dataframe : Duplicating rows according to the number of items in a list and ranking the resulted rowsPython,数据框:根据列表中的项目数复制行并对结果行进行排名
【发布时间】:2017-03-03 14:46:40
【问题描述】:

我的 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   

感谢您的帮助。

【问题讨论】:

    标签: python list pandas dataframe


    【解决方案1】:

    您需要使用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())))
    

    【讨论】:

    • 第二个效果很好,谢谢。第一个很好,但它也复制了索引,它不会增加它们。
    • 我修改了第一个选项,使其提供唯一索引,它现在应该也可以工作了。
    【解决方案2】:

    这是我的解决方案:

    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 它也应该适用于具有多列的通用数据帧

    【讨论】:

      猜你喜欢
      • 2019-03-07
      • 2011-08-13
      • 2018-12-12
      • 1970-01-01
      • 2012-06-19
      • 1970-01-01
      • 2017-10-17
      • 2014-12-29
      • 1970-01-01
      相关资源
      最近更新 更多