如何将其值为列表的列的数据框转换为该列中每个列表的每个元素变为新行的数据框

时间:2019-12-01 17:58:54

标签: python pandas

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

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
...

*请注意,user_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

如您所见,我什至尝试为数据帧预分配内存,但这似乎并没有太大帮助。

因此,必须有一种更好的方法来执行此操作。谁能帮我吗?

3 个答案:

答案 0 :(得分:1)

使用split将列表转换为实际列表,然后使用explode扩展DataFrame。 需要熊猫> = 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

答案 1 :(得分:1)

首先,您的item_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')

答案 2 :(得分:1)

尝试一下:

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()