【问题标题】:merging varying number of rows by multiple conditions in python在python中通过多个条件合并不同数量的行
【发布时间】:2021-06-11 11:43:42
【问题描述】:

问题:通过多个条件合并不同数量的行

这是数据集外观的风格示例

"index" "connector" "type" "q_text" "a_text" "varx" ...
   1        1111      1      aa       NA       xx
   2        9999      2      NA       tt       NA
   3        1111      2      NA       uu       NA
   4        9999      1      bb       NA       yy
   5        9999      1      cc       NA       zz

目标:数据集应该的样子

"index" "connector" "type" "type.1" "q_text" "q_text.1" "a_text" "a_text.1 " "varx" "varx.1" ...
   1        1111      1       2        aa        NA        NA        uu        xx      NA
   2        9999      1       2        bb        NA        NA        tt        yy      NA
   3        9999      1       2        cc        NA        NA        tt        zz      NA

逻辑:列“type”的值为 1 或 2,而多行的值为 1,但只有一行(“connector”中的值相同)值为 2

如果 “连接器”中的相同值 然后 合并 “type”行=2,“type”行=1 但是 (因为“type”=1的多行在“connector”中有相同的值) 重复 type=2 的对应行 和 合并 在“connector”中也具有相同值且属于“type”=1 的所有其他行

我的结果:并非所有结果都被合并,因为“type”=1 的多行与“type”=2 的 UNIQUE 行相关联

大多数类似的问题都是用 SQL 来回答的,我在这里不能用。

df2 = df.copy()
df.index.astype(str)
df2.index.astype(str)
pd.merge(df,df2, how='left', on='connector',right_index=True, left_index=True)
df3 = pd.merge(df.set_index('connector'),df2.set_index('connector'), right_index=True, left_index=True).reset_index()
dfNew = df.merge(df2, how='left', left_on=['connector'], right_on = ['connector'])

我可以通过 goupby() 实现我的目标吗?

@victor__von__doom 的解决方案

if __name__ == '__main__':
    df = df.groupby('connector', sort=True).apply(lambda c: list(zip(*c.values[:,2:].tolist()))).reset_index(name='merged')
    df[['here', 'are', 'all', 'columns', 'except', 'for', 'the', 'connector', 'column']]  = pd.DataFrame(df.merged.tolist())
    df = df.drop(['merged'], axis=1)

【问题讨论】:

    标签: python-3.x dataframe validation merge pandas-groupby


    【解决方案1】:

    首先,在合并行时,将新列连接到原始DataFrame 上真的很麻烦,尤其是当列数非常大时。此外,如果您最终为 1 个连接器值合并 3 行,为另一个(例如)合并 4 行,包含所有值的唯一方法是为某些行创建空列,这绝不是一个好主意。相反,我这样做是为了将合并的行组合成元组,然后可以有效地解析这些元组,同时保持 DataFrame 的大小易于管理:

    import numpy as np
    import pandas as pd
    
    if __name__ == '__main__':
        data = np.array([[1,2,3,4,5], [1111,9999,1111,9999,9999],
                         [1,2,2,1,1], ['aa', 'NA', 'NA', 'bb', 'cc'],
                         ['NA', 'tt', 'uu', 'NA', 'NA'],
                         ['xx', 'NA', 'NA', 'yy', 'zz']])
    
        df = pd.DataFrame(data.T, columns = ["index", "connector",
                              "type", "q_text", "a_text", "varx"])
    
        df = df.groupby("connector", sort=True).apply(lambda c: list(zip(*c.values[:,2:].tolist()))).reset_index(name='merged')
        df[["type", "q_text", "a_text", "varx"]]  = pd.DataFrame(df.merged.tolist())
        df = df.drop(['merged'], axis=1)
    

    最终的DataFrame 看起来像:

      connector       type        q_text        a_text          varx ...
    0      1111     (1, 2)      (aa, NA)      (NA, uu)      (xx, NA) ...
    1      9999  (2, 1, 1)  (NA, bb, cc)  (tt, NA, NA)  (NA, yy, zz) ...
    

    这更紧凑和可读。

    【讨论】:

    • 谢谢,这听起来很有用,也是一种更好的方法。我收到错误 ValueError: Columns must be same length as key 并在问题末尾添加了我改编自您的代码
    • 奇怪 - 我发布的代码在我的系统上完美运行。您能确定导致错误的确切原因吗?如果没有,您可以发布您改编的代码吗?你可能错过了什么。
    • 好的,当您写“除连接器列之外的所有列”时,是否包括“索引”列?这是您创建的实际列,还是默认的 pandas 索引列?如果这是默认的 pandas 之一(不是您创建的),那么您需要将 zip(*c.values[:,2:]... 更改为 zip(*c.values[:,1:]...。无论哪种方式,听起来错误来自我所做的pd.DataFrame(df.merged.tolist()) 的行 - 它以某种方式解压了错误的列数。
    • 代码在上述问题的末尾。也许是因为我没有在代码中包含“索引”列?我有一个自然索引,但没有一个单独的“索引”列,你的代码说类似[:,2:],而我实际上并没有把这两个排除在外,而只有“连接器”列,因为我试图在代码末尾突出显示题。那我试试[:,1:]
    • 是的,这就是问题所在。我包含了一个显式索引列,所以我从第二列(索引 + 连接器)切分,但是根据您的设置,您应该只从第一列(连接器)切分。如果将其更改为[:,1:],它应该可以正常工作。
    猜你喜欢
    • 2021-06-12
    • 2021-07-26
    • 2019-04-23
    • 2015-04-21
    • 2020-11-09
    • 1970-01-01
    • 2017-02-17
    • 1970-01-01
    • 2020-11-02
    相关资源
    最近更新 更多