我的pandas数据框中的一列包含一个列表。 我想扩展它并转换如下的垂直形状。 怎么做?
在(代码):
import pandas as pd
pd.DataFrame({
'col1':['fruit', 'veicle', 'animal'],
'col2':['apple', 'bycicle', 'cat'],
'col3':[1,4,2],
'list':[
[10, 20],
[1.2, 3.0, 2.75],
['tommy', 'tom']
]
})
在(表):
|col1 |col2 |col3|list |
|------|-------|----|----------------|
|fruit |apple | 1|[10, 20] |
|veicle|bicycle| 4|[1.2, 3.0, 2.75]|
|animal|cat | 2|['tommy', 'tom']|
在
|col1 |col2 |col3|list |
|------|-------|----|-------|
|fruit |apple | 1|10 |
|fruit |apple | 1|20 |
|viecle|bycicle| 4|1.2 |
|viecle|bycicle| 4|3.0 |
|viecle|bycicle| 4|2.75 |
|animal|cat | 2|'tommy'|
|animal|cat | 2|'tom |
注1:列表的长度和类型不同。
注意2:我可以 NOT 修改生成datafarme的代码。
感谢您的阅读。
答案 0 :(得分:5)
您可以set_index前三列,然后将pd.Series
应用于列的列,然后将它们堆叠。
df.set_index(['col1','col2','col3'])['list'].apply(pd.Series).stack().reset_index().drop('level_3',axis=1)
输出:
col1 col2 col3 0 0 fruit apple 1 10 1 fruit apple 1 20 2 veicle bycicle 4 1.2 3 veicle bycicle 4 3 4 veicle bycicle 4 2.75 5 animal cat 2 tommy 6 animal cat 2 tom
答案 1 :(得分:3)
前几天使用np.repeat
和np.concatenate
从piR学到了这个很酷的技巧:
idx = np.arange(len(df)).repeat(df.list.str.len(), 0)
out = df.iloc[idx, :-1].assign(list=np.concatenate(df.list.values))
print(out)
col1 col2 col3 list
0 fruit apple 1 10
0 fruit apple 1 20
1 veicle bycicle 4 1.2
1 veicle bycicle 4 3.0
1 veicle bycicle 4 2.75
2 animal cat 2 tommy
2 animal cat 2 tom
效果
# Bharath
%timeit df.set_index(['col1','col2','col3']['list'].apply(pd.Series).stack()\
.reset_index().drop('level_3',axis=1)
100 loops, best of 3: 7.75 ms per loop
# Mine
%%timeit
idx = np.arange(len(df)).repeat(df.list.str.len(), 0)
out = df.iloc[idx, :-1].assign(list=np.concatenate(df.list.values))
1000 loops, best of 3: 1.41 ms per loop
df_test = pd.concat([df] * 10000)
# Bharath
%timeit df_test.set_index(['col1','col2','col3'])['list'].apply(pd.Series).stack()\
.reset_index().drop('level_3',axis=1)
1 loop, best of 3: 7.09 s per loop
# Mine
%%timeit
idx = np.arange(len(df_test)).repeat(df_test.list.str.len(), 0)
out = df_test.iloc[idx, :-1].assign(list=np.concatenate(df_test.list.values))
10 loops, best of 3: 123 ms per loop
作为一个班轮,Bharath的回答很短,但很慢。以下是使用数据框构造函数而不是df.apply
对大数据进行200倍加速的改进:
idx = df.set_index(['col1', 'col2', 'col3']).index
out = pd.DataFrame(df.list.values.tolist(), index=idx).stack()\
.reset_index().drop('level_3', 1).rename(columns={0 : 'list'})
print(out)
col1 col2 col3 list
0 fruit apple 1 10
1 fruit apple 1 20
2 veicle bycicle 4 1.2
3 veicle bycicle 4 3
4 veicle bycicle 4 2.75
5 animal cat 2 tommy
6 animal cat 2 tom
100 loops, best of 3: 4.7 ms per loop
10 loops, best of 3: 28.9 ms per loop
答案 2 :(得分:0)
以下是关于如何完成此任务的大致内容。这不是确切的解决方案,但会让您了解如何完成任务:
original_df = <your dataframe to start>
new_empty_df = pd.DataFrame()
# now go through each row of the original df
for i in range(original_df.shape[0]):
row_Series = original_df.iloc[i]
row_list = row_Series['list']
for item in row_list:
new_empty_df.append({'col1':row_Series['col1'],
'col2':row_Series['col2'],
'list':item})