Pandas从列中可用的列表数据中扩展行

问题描述 投票:12回答:3

我在熊猫中有这样的数据框:

 column1      column2
 [a,b,c]        1
 [d,e,f]        2
 [g,h,i]        3

Expected output:

column1      column2
  a              1
  b              1
  c              1
  d              2
  e              2
  f              2
  g              3
  h              3
  i              3

如何处理这些数据?

python list pandas dataframe expand
3个回答
17
投票

你可以通过它的构造函数和DataFrame创建stack

 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,然后由Seriesstack创建join到原始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

4
投票

另一个解决方案是使用自pandas 0.23以来可用的result_type='expand'函数的pandas.apply参数。回答@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']]

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
© www.soinside.com 2019 - 2024. All rights reserved.