【问题标题】:Python - Split multiple columns into multiple rowsPython - 将多列拆分为多行
【发布时间】:2018-12-14 05:26:21
【问题描述】:

我试图在几行中将多列拆分为多行,而不是为它编写一个大的“def 函数”。 我有 2 列需要按 ; 拆分。我正在尝试遵循:Split cell into multiple rows in pandas dataframe

from pandas import DataFrame
import numpy as np
from itertools import chain
import pandas as pd

a = DataFrame([{'var1': 'a;b;c', 'var2': 1,'var3':'apples;mango'},
            {'var1': 'd;e;f', 'var2': 2,'var3':'kiwi;pineapple'},
            {'var1': 'g;e;a', 'var2': 15,'var3':'pinneapple'},
            {'var1': 'm', 'var2': 12,'var3':'orange'}])
a

# return list from series of comma-separated strings
def chainer(s):
    return list(chain.from_iterable(s.str.split(';')))

# calculate lengths of splits
lens = a['var1'].str.split(';').map(len)

# create new dataframe, repeating or chaining as appropriate
new_df = pd.DataFrame({'var1': chainer(a['var1']),
                    'var2': np.repeat(a['var2'], lens),
                    'var3': chainer(a['var3'])
                })

print(new_df)

#ERROR: ValueError: arrays must all be same length

寻找这样的输出:

【问题讨论】:

  • 您似乎尝试的jpp 解决方案的主要区别是您想要var1var3 中值的笛卡尔积(例如第一行有输出中的 3*2 行)而当package 中的任何值与package code 中的一个值相关联时写入解决方案。

标签: python python-3.x pandas


【解决方案1】:

这里更适合使用产品:

import itertools

def splitter(values):
    return list(itertools.product( *[str(v).split(';') for v in values]))

In [6]: splitter(df.iloc[2]) #example
Out[6]: 
[('g', '15', 'pinneapple'),
 ('e', '15', 'pinneapple'),
 ('a', '15', 'pinneapple')]

现在,对所有行执行此操作并重建一个新的数据框:

def expand(df):
    tuples=list()
    for i,row in df.iterrows():
        tuples.extend(splitter(row))
    return  pd.DataFrame.from_records(tuples,columns=df.columns)

结果:

In [7]: expand(df)
   var  var2        var3
0     a    1      apples
1     a    1       mango
2     b    1      apples
3     b    1       mango
4     c    1      apples
5     c    1       mango
6     d    2        kiwi
7     d    2   pineapple
8     e    2        kiwi
9     e    2   pineapple
10    f    2        kiwi
11    f    2   pineapple
12    g   15  pinneapple
13    e   15  pinneapple
14    a   15  pinneapple
15    m   12      orange

【讨论】:

    【解决方案2】:

    试试下面的代码:

    import pandas as pd
    
    # Source data
    a = pd.DataFrame([{'var1': 'a;b;c', 'var2': 1,'var3':'apples;mango'},
        {'var1': 'd;e;f', 'var2':  2,'var3':'kiwi;pineapple'},
        {'var1': 'g;e;a', 'var2': 15,'var3':'pinneapple'},
        {'var1': 'm',     'var2': 12,'var3':'orange'}])
    # Split var1
    a2 = a.var1.apply(lambda t: pd.Series(t.split(';')))\
        .merge(a, right_index = True, left_index = True)\
        .drop(['var1'], axis = 1)\
        .melt(id_vars = ['var2', 'var3'], value_name = 'var1')\
        .drop('variable', axis = 1).dropna()
    # Split var3
    a3 = a2.var3.apply(lambda t: pd.Series(t.split(';')))\
        .merge(a2, right_index = True, left_index = True)\
        .drop(['var3'], axis = 1)\
        .melt(id_vars = ['var1', 'var2'], value_name = 'var3')\
        .drop('variable', axis = 1).dropna()
    # Sort the result
    a3.sort_values(['var2', 'var3'])
    

    a2 包含一个表,其中var1 分为单独的行。

    var3 的相同操作执行下一条指令(类似于 以前的名称已更改。

    最后一步是对结果进行排序。

    要了解此代码的工作原理,请分别执行每个步骤 链接指令之一。

    如果你有更多的列要分割,添加类似的“分割” 给他们的说明。

    【讨论】:

      【解决方案3】:

      在每列上使用 str.splitstack 后,您可以在每列上 join。这可以通过首先定义一个函数来获得正确形状的列来完成:

      def split_stack_col (a_col):
          return (a_col.astype(str).str.split(';',expand=True).stack()
                       .reset_index(level=1,name=a_col.name)[[a_col.name]])
      

      然后你map这个函数在使用reduce和join之前的每一列。如果需要,添加一个 reset_index

      from functools import reduce
      new_df = reduce(lambda x,y: x.join(y), 
                      map( split_stack_col, 
                           (a[col] for col in a.columns))).reset_index(drop=True)
      

      此方法可用于a 中的任意数量的列,并且您得到了预期的结果:

      print (new_df)
         var1 var2        var3
      0     a    1      apples
      1     a    1       mango
      2     b    1      apples
      3     b    1       mango
      4     c    1      apples
      5     c    1       mango
      6     d    2        kiwi
      7     d    2   pineapple
      8     e    2        kiwi
      9     e    2   pineapple
      10    f    2        kiwi
      11    f    2   pineapple
      12    g   15  pinneapple
      13    e   15  pinneapple
      14    a   15  pinneapple
      15    m   12      orange
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-16
        • 1970-01-01
        • 1970-01-01
        • 2020-02-10
        相关资源
        最近更新 更多