如何将列中的列表转换为垂直形状?
How to convert list in columns to vertical shape?
我的 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']
]
})
之前(table):
|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:我可以不能修改生成datafarme的代码。
感谢阅读。
前几天从 piR 那里学到了这个很酷的技巧,使用 np.repeat
和 np.concatenate
:
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
作为 1 班轮,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
你可以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
以下是完成此任务的大致方法。这不是确切的解决方案,但可以让您了解如何完成任务:
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})
我的 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']
]
})
之前(table):
|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:我可以不能修改生成datafarme的代码。
感谢阅读。
前几天从 piR 那里学到了这个很酷的技巧,使用 np.repeat
和 np.concatenate
:
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
作为 1 班轮,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
你可以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
以下是完成此任务的大致方法。这不是确切的解决方案,但可以让您了解如何完成任务:
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})