有条件分割长行的最Pythonic /最有效的方法是什么?

时间:2019-10-11 16:23:31

标签: python-3.x pandas numpy dataframe

我有一个数据列,其中列Results可能会很长。由于数据框最终出现在Excel报表中,因此这是有问题的,因为Excel仅在不显示所有数据之前才会排成一行。相反,我想做的是将具有一定长度的结果的行拆分为多行。

我在小规模的数据框架上编写了一些代码,将结果分成2个大块。我还没有弄清楚如何将每个大块放入新行中。另外,当我的数据帧从6行增加到35k +时,我不确定这将是最有效的方法。什么是实现我想要的最有效/ Pythonic方法?

原始数据框

                        Result        Date
0                    [SUCCESS]  10/10/2019
1                    [SUCCESS]  10/09/2019
2                    [FAILURE]  10/08/2019
3  [Pending, Pending, SUCCESS]  10/07/2019
4                    [FAILURE]  10/06/2019
5           [Pending, SUCCESS]  10/05/2019

目标输出

               Result        Date
0           [SUCCESS]  10/10/2019
1           [SUCCESS]  10/09/2019
2           [FAILURE]  10/08/2019
3  [Pending, Pending]  10/07/2019
4           [SUCCESS]  10/07/2019
5           [FAILURE]  10/06/2019
6  [Pending, SUCCESS]  10/05/2019

代码

import pandas as pd
import numpy as np

data = {'Result': [['SUCCESS'], ['SUCCESS'], ['FAILURE'], ['Pending', 'Pending', 'SUCCESS'], ['FAILURE'], ['Pending', 'SUCCESS']], 'Date': ['10/10/2019', '10/09/2019', '10/08/2019', '10/07/2019', '10/06/2019', '10/05/2019']}

df = pd.DataFrame(data)
df['Length of Results'] = df['Result'].str.len()

def chunks(l, n):
    for i in range(0, len(l), n):
        yield l[i:i + n]

for i in range(len(df)):
    if df['Length of Results'][i] > 2:
        df['Result'][i] = list(chunks(df['Result'][i], 2))
    else:
        pass

df['Chunks'] = 1
for i in range(len(df)):
    if df['Length of Results'][i] > 2:
        df['Chunks'][i] = len(df['Result'][i])
    else:
        pass

df = df.loc[np.repeat(df.index.values, df.Chunks)]
df = df.reset_index(drop=True)

当前产生的代码

                            Result        Date  Length of Results  Chunks
0                        [SUCCESS]  10/10/2019                  1       1
1                        [SUCCESS]  10/09/2019                  1       1
2                        [FAILURE]  10/08/2019                  1       1
3  [[Pending, Pending], [SUCCESS]]  10/07/2019                  3       2
4  [[Pending, Pending], [SUCCESS]]  10/07/2019                  3       2
5                        [FAILURE]  10/06/2019                  1       1
6               [Pending, SUCCESS]  10/05/2019                  2       1

df.to_dict()

{'Result': {0: ['SUCCESS'], 1: ['SUCCESS'], 2: ['FAILURE'], 3: [['Pending', 'Pending'], ['SUCCESS']], 4: [['Pending', 'Pending'], ['SUCCESS']], 5: ['FAILURE'], 6: ['Pending', 'SUCCESS']}, 'Date': {0: '10/10/2019', 1: '10/09/2019', 2: '10/08/2019', 3: '10/07/2019', 4: '10/07/2019', 5: '10/06/2019', 6: '10/05/2019'}, 'Length of Results': {0: 1, 1: 1, 2: 1, 3: 3, 4: 3, 5: 1, 6: 2}, 'Chunks': {0: 1, 1: 1, 2: 1, 3: 2, 4: 2, 5: 1, 6: 1}}

2 个答案:

答案 0 :(得分:1)

您可以

s=df[['Date','Result']].explode('Result')

t=s.groupby(['Date','Result'])['Result'].transform('size')>1
s.groupby([s.Date,t]).Result.agg(list).reset_index(level=0).reset_index(drop=True)
Out[65]: 
         Date              Result
0  10/05/2019  [Pending, SUCCESS]
1  10/06/2019           [FAILURE]
2  10/07/2019           [SUCCESS]
3  10/07/2019  [Pending, Pending]
4  10/08/2019           [FAILURE]
5  10/09/2019           [SUCCESS]
6  10/10/2019           [SUCCESS]

答案 1 :(得分:1)

如果熊猫0.25+以上,我建议使用pending/SUCCESS/FAILURE将每个df.explode放在一行中。

df = df.explode('Result')
df.groupby(['Date','Result']).count().reset_index(name='Length')

输出:

         Date   Result  Length
0  10/05/2019  Pending       1
1  10/05/2019  SUCCESS       1
2  10/06/2019  FAILURE       1
3  10/07/2019  Pending       2
4  10/07/2019  SUCCESS       1
5  10/08/2019  FAILURE       1
6  10/09/2019  SUCCESS       1
7  10/10/2019  SUCCESS       1