【问题标题】:Split list in row into multiple chunked rows将行中的列表拆分为多个分块行
【发布时间】:2019-10-15 15:02:40
【问题描述】:

我有一个 pandas 数据框,其中一些行包含从系统返回的结果列表。我试图将这些列表分成更小的块(在下面的可重现示例中,2 个块),每个块作为一个新行。我确实发现我可以使用 numpy 的 repeat 函数来复制行,以便为我需要的每个块保留一行,但是我不确定如何只在 Result 中包含列表的一部分。 (即一行应该是['SUCCESS', 'Misc],下一个是['Doom'],而不是一行[['SUCCESS', 'Misc'],['Doom']]

我知道最好的解决方案是使用explode 将列表中的每个项目都设为一个新行,但由于客户要求,这不是一个选项。

代码

import pandas as pd
import numpy as np

data = {'Result': [['SUCCESS'], ['SUCCESS'], ['FAILURE'], ['Pending', 'Pending', 'SUCCESS', 'Misc', 'Doom'], ['FAILURE'], ['Pending', 'SUCCESS']], 'Date': ['10/10/2019', '10/09/2019', '10/08/2019', '10/07/2019', '10/06/2019', '10/05/2019']}
goal = {'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', '10/04/2019']}

df = pd.DataFrame(data)

df['len_res'] = df['Result'].str.len()

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


df['chunks'] = 1
for i in range(len(df)):
    if df['len_res'][i] > 2:
        df['Result'][i] = list(chunking(df['Result'][i], 2))
        df['chunks'][i] = len(df['Result'][i])
    else:
        pass

实际输出

                                          Result        Date  len_res  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, Misc], [Doom]]  10/07/2019        5       3
4                                      [FAILURE]  10/06/2019        1       1
5                             [Pending, SUCCESS]  10/05/2019        2       1

期望的输出

                                          Result        Date  len_res  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]  10/07/2019        5       3
4                                [SUCCESS, Misc]  10/07/2019        5       3
5                                         [Doom]  10/07/2019        5       3
6                                      [FAILURE]  10/06/2019        1       1
7                             [Pending, SUCCESS]  10/05/2019        2       1

np.repeat

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

                                          Result        Date  len_res  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, Misc], [Doom]]  10/07/2019        5       3
4  [[Pending, Pending], [SUCCESS, Misc], [Doom]]  10/07/2019        5       3
5  [[Pending, Pending], [SUCCESS, Misc], [Doom]]  10/07/2019        5       3
6                                      [FAILURE]  10/06/2019        1       1
7                             [Pending, SUCCESS]  10/05/2019        2       1

【问题讨论】:

    标签: python-3.x pandas dataframe


    【解决方案1】:

    如果您使用的是 pandas v0.25 或更高版本,请使用explode

    size = 2
    df['Result'] = df['Result'].apply(lambda r: np.array_split(r, np.ceil(len(r) / size)))
    df['chunks'] = df['Result'].str.len()
    
    df = df.explode('Result')
    

    np.array_split 将数组拆分为 n = ceil(len(r) / size) 部分:

    [1]     --> [[1]]
    [1,2]   --> [[1,2]]
    [1,2,3] --> [[1,2], [3]]
    

    explodeResult 中数组最外层的每个元素重复每一行。

    【讨论】:

    • 这非常优雅和高效,完全符合我的需要。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2021-10-23
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 2018-11-02
    • 2020-12-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多