代码之家  ›  专栏  ›  技术社区  ›  Luca Guarro

如何将具有值为列表的列的数据帧转换为该列中每个列表元素都成为新行的数据帧

  •  2
  • Luca Guarro  · 技术社区  · 5 年前

    我有一个数据框,其中的条目格式如下:

    user_id,item_list
    0,3569 6530 4416 5494 6404 6289 10227 5285 3601 3509 5553 14879 5951 4802 15104 5338 3604 2345 9048 8627
    1,16148 8470 7671 8984 9795 6811 3851 3611 7662 5034 5301 6948 5840 345 14652 10729 8429 7295 4949 16144
    ...
    

    *注意,用户id不是数据帧的索引

    我要将数据帧转换为如下所示:

    user_id,item_id
    0,3569
    0,6530
    0,4416 
    0,5494 
    ...
    1,4949
    1,16144
    ...
    

    现在我正在尝试,但是效率太低了:

    df = pd.read_csv("20recs.csv")
    numberOfRows = 28107*20
    df2 = pd.DataFrame(index=np.arange(0, numberOfRows),columns=('user', 'item'))
    iter = 0
    for index, row in df.iterrows():
        user = row['user_id']
        itemList = row['item_list']
        items = itemList.split(' ')
        for item in items:
            df2.loc[iter] = [user]+[item]
            iter = iter + 1
    

    如您所见,我甚至尝试为数据帧预先分配内存,但似乎没有多大帮助。

    所以一定有更好的办法。有人能帮我吗?

    4 回复  |  直到 5 年前
        1
  •  1
  •   mcsoini    5 年前

    使用 split 要将列表转换为实际列表,则 explode 去。。。好吧,爆炸数据框。 需要熊猫>=0.25.0

    >>> df = pd.DataFrame({'user_id': [0,1], 'item_list': ['1 2 3', '4 5 6']})
    >>> df
    
       user_id item_list
    0        0     1 2 3
    1        1     4 5 6
    
    >>> (df.assign(item_id=df.item_list.apply(lambda x: x.split(' ')))
           .explode('item_id')[['user_id', 'item_id']])
    
       user_id   item_id
    0        0         1
    0        0         2
    0        0         3
    1        1         4
    1        1         5
    1        1         6
    
    
        2
  •  1
  •   SchwarzeHuhn    5 年前

    首先,您的项目id列应该是一个列表

    df['item_id_list'] = df['item_id'].str.split(',').values.tolist()
    df['item_id_list_int'] = [[int(i) for i in x] for x in df['item_id_list']]
    

    然后你引爆它

    df_exp = df.explode('item_id_list_int')
    
        3
  •  1
  •   oppressionslayer    5 年前

    试试这个:

    df.set_index('user_id').item_list.apply(lambda x: x.split(' ')).explode().reset_index().set_index('user_id') 
    

    输出

            item_list
    user_id          
    0            3569
    0            6530
    0            4416
    0            5494
    0            6404
    0            6289
    0           10227
    0            5285
    0            3601
    0            3509
    0            5553
    0           14879
    0            5951
    0            4802
    0           15104
    0            5338
    0            3604
    0            2345
    0            9048
    0            8627
    1           16148
    1            8470
    1            7671
    1            8984
    1            9795
    1            6811
    1            3851
    1            3611
    1            7662
    1            5034
    1            5301
    1            6948
    1            5840
    1             345
    1           14652
    1           10729
    1            8429
    1            7295
    1            4949
    1           16144
    

    或者如果要索引:

    df.set_index('user_id').item_list.apply(lambda x: x.split(' ')).explode().reset_index()
    
        4
  •  -1
  •   davidbilla    5 年前

    值0和1是原始数据帧的索引吗? 可以拆分列表并使用“分解”选项(需要熊猫0.25或更高版本)

    df['item_list'] = [x for x in df.item_list.str.split(' ')]
    df.explode('item_list')