Python-将多列拆分为多行

时间:2018-12-13 19:28:31

标签: python python-3.x pandas

我试图将几行分成几行,而不是为其编写一个大的“ 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

寻找这样的输出: enter image description here

3 个答案:

答案 0 :(得分:0)

在这里更适合使用产品:

.thumb{
  float:left;
  margin:5px;
}

#gallery{
  width:850px;
  display: flex;
  flex-wrap: wrap;
}

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

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)

答案 1 :(得分:0)

尝试以下代码:

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的相同操作将执行下一条指令(类似于 以前的名称已更改。

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

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

如果要划分的列更多,请添加类似的“拆分” 给他们的说明。

答案 2 :(得分:0)

在每一列上分别使用joinstr.split后,您就可以stack每列。这可以通过首先定义一个函数来使列的形状正确来完成:

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对每个列使用此函数。如果需要,添加一个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