我在pandas中有这样的数据框:
column1 column2
[a,b,c] 1
[d,e,f] 2
[g,h,i] 3
column1 column2
a 1
b 1
c 1
d 2
e 2
f 2
g 3
h 3
i 3
如何处理这些数据?
答案 0 :(得分:13)
您可以通过其构造函数stack
创建DataFrame
:
df2 = pd.DataFrame(df.column1.tolist(), index=df.column2)
.stack()
.reset_index(level=1, drop=True)
.reset_index(name='column1')[['column1','column2']]
print (df2)
column1 column2
0 a 1
1 b 1
2 c 1
3 d 2
4 e 2
5 f 2
6 g 3
7 h 3
8 i 3
如果需要按子集[['column1','column2']]
更改排序,您还可以省略reset_index
:
df2 = pd.DataFrame(df.column1.tolist(), index=df.column2)
.stack()
.reset_index(name='column1')[['column1','column2']]
print (df2)
column1 column2
0 a 1
1 b 1
2 c 1
3 d 2
4 e 2
5 f 2
6 g 3
7 h 3
8 i 3
另一个解决方案DataFrame.from_records
,用于从第一列创建DataFrame
,然后按stack
和join
创建Series
到原始DataFrame
:
df = pd.DataFrame({'column1': [['a','b','c'],['d','e','f'],['g','h','i']],
'column2':[1,2,3]})
a = pd.DataFrame.from_records(df.column1.tolist())
.stack()
.reset_index(level=1, drop=True)
.rename('column1')
print (a)
0 a
0 b
0 c
1 d
1 e
1 f
2 g
2 h
2 i
Name: column1, dtype: object
print (df.drop('column1', axis=1)
.join(a)
.reset_index(drop=True)[['column1','column2']])
column1 column2
0 a 1
1 b 1
2 c 1
3 d 2
4 e 2
5 f 2
6 g 3
7 h 3
8 i 3
答案 1 :(得分:3)
另一种解决方案是使用自{pandas 0.23以来可用的pandas.apply
函数的result_type='expand'
参数。回答@splinter's question可以概括此方法-参见下文:
import pandas as pd
from numpy import arange
df = pd.DataFrame(
{'column1' : [['a','b','c'],['d','e','f'],['g','h','i']],
'column2': [1,2,3]}
)
pd.melt(
df.join(
df.apply(lambda row: row['column1'], axis=1, result_type='expand')
),
value_vars=arange(df['column1'].shape[0]), value_name='column1', var_name='column2')[['column1','column2']]
# can be generalized
df = pd.DataFrame(
{'column1' : [['a','b','c'],['d','e','f'],['g','h','i']],
'column2': [1,2,3],
'column3': [[1,2],[2,3],[3,4]],
'column4': [42,23,321],
'column5': ['a','b','c']}
)
(pd.melt(
df.join(
df.apply(lambda row: row['column1'], axis=1, result_type='expand')
),
value_vars=arange(df['column1'].shape[0]), value_name='column1', id_vars=df.columns[1:])
.drop(columns=['variable'])[list(df.columns[:1]) + list(df.columns[1:])]
.sort_values(by=['column1']))
更新(Jwely的评论): 如果列表的长度不同,则可以执行以下操作:
df = pd.DataFrame(
{'column1' : [['a','b','c'],['d','f'],['g','h','i']],
'column2': [1,2,3]}
)
longest = max(df['column1'].apply(lambda x: len(x)))
pd.melt(
df.join(
df.apply(lambda row: row['column1'] if len(row['column1']) >= longest else row['column1'] + [None] * (longest - len(row['column1'])), axis=1, result_type='expand')
),
value_vars=arange(df['column1'].shape[0]), value_name='column1', var_name='column2').query("column1 == column1")[['column1','column2']]
答案 2 :(得分:0)
我们执行此操作的另一种方法是使用iterrows()
遍历数据帧中的每一行。由于它使用for loops
,因此从速度上讲可能不是那么快,但可读性更高。
# Create lists to fill with values
l_col1 = []
l_col2 = []
# iterrate over each row and fill our lists
for ix, row in df.iterrows():
for value in row['column1']:
l_col1.append(value)
l_col2.append(row['column2'])
# Create new dataframe from the two lists
df_final = pd.DataFrame({'column1': l_col1 ,
'column2': l_col2 })
print(df_final)
column1 column2
0 a 1
1 b 1
2 c 1
3 d 2
4 e 2
5 f 2
6 g 3
7 h 3
8 i 3