【问题标题】:In python, if ID matches, move row to column while summing specific columns在python中,如果ID匹配,则在对特定列求和时将行移到列
【发布时间】:2022-09-24 00:47:41
【问题描述】:

我在单独的行中有配偶的数据,但每个配偶共享相同的 ID。在某些情况下,这些 ID 位于多行上。当 ID 匹配时,我需要将配偶行移动到一列,因此配偶双方共享一行。然后我还需要对值求和。

输入

   ID  Position  Title  First  Last  SpTitle  SpFirst  SpLast  Address    Value1  Value2  Value3
0  456 HoH       Mr.    John   Doe   NaN      NaN      NaN     123 street  10      NaN     30
1  456 Spouse    Mrs.   Jane   Doe   NaN      NaN      NaN     123 street  10      NaN     30
2  789 HoH       Mrs.   Jane   Doe   NaN      NaN      NaN     456 road    100     200     300
3  789 HoH       Mrs.   Jane   Doe   NaN      NaN      NaN     456 road    400     500     600
4  789 Spouse    Mr.    John   Doe   NaN      NaN      NaN     456 road    NaN     10      30

期望的输出

   ID  Position  Title  First  Last  SpTitle  SpFirst  SpLast  Address    Value1  Value2  Value3
0  456 HoH       Mr.    John   Doe   Mrs.     Jane     Doe     123 street  20      NaN     60
1  789 HoH       Mrs.   Jane   Doe   Mr.      John     Doe     456 road    500     710     930

有数千行。一些 ID 重复了几十行。我认为它会使用groupbyagg,但我似乎无法让它正常工作。

当 ID 匹配时,如何在求和值时移动配偶与户主 (HoH) 共享同一行?

这是我到目前为止所拥有的:

import pandas as pd
import numpy as np

# Combine sheets
df = pd.concat(pd.read_excel(\"C:/Users/Sheet.xlsx\", sheet_name=None), ignore_index=True)

# Drop blank IDs
df = df[df[\'ID\'].notna()]

# Insert Spouse columns
df.insert(loc = 10, column=\'SpTitle\', value = \'\')
df.insert(loc = 11, column=\'SpFirstName\', value = \'\')
df.insert(loc = 12, column=\'SpMiddleName\', value = \'\')
df.insert(loc = 13, column=\'SpLastname\', value = \'\')
df.insert(loc = 14, column=\'SpBirthDate\', value = \'\')
df.insert(loc = 15, column=\'SpGender\', value = \'\')

m = df.Position.eq(\"Spouse\")

df.loc[m, [\"SpTitle\", \"SpFirstName\", \"SpMiddleName\", \"SpLastName\", \"SpBirthDate\", \"SpGender\" ]] = df.loc[
    m, [\"Title\", \"First Name\", \"Middle Name\", \"Last Name\", \"Gender\", \"Date of Birth\"]
].values

df[[\"Value 2019\", \"Value 2020\", \"Value 2021\", \"Value 2022\", \"Fund 2019\", \"Fund 2020\", \"Fund 2022\", \"Fund 2021\"]] = df.groupby(\"ID\", as_index=False)[
    [\"Value  2019\", \"Value 2020\", \"Value 2021\", \"Value 2022\", \"Fund 2019\", \"Fund 2020\", \"Fund 2022\", \"Fund 2021\"]
].transform(np.sum, min_count=1)

df[[\"SpTitle\", \"SpFirstName\", \"SpMiddleName\", \"SpLastName\", \"SpBirthDate\", \"SpGender\"]] = df.groupby(\"ID\", as_index=False)[
    [\"SpTitle\", \"SpFirstName\", \"SpMiddleName\", \"SpLastName\", \"SpBirthDate\", \"SpGender\"]
].transform(lambda x: x.ffill().bfill())

df = df[~m].drop_duplicates()

df.to_csv(\"C:/Users/data.csv\", index = False)

    标签: python pandas dataframe group-by


    【解决方案1】:

    尝试:

    m = df.Position.eq("Spouse")
    
    df.loc[m, ["SpTitle", "SpFirst", "SpLast"]] = df.loc[
        m, ["Title", "First", "Last"]
    ].values
    
    df[["Value1", "Value2", "Value3"]] = df.groupby("ID", as_index=False)[
        ["Value1", "Value2", "Value3"]
    ].transform(np.sum, min_count=1)
    
    df[["SpTitle", "SpFirst", "SpLast"]] = df.groupby("ID", as_index=False)[
        ["SpTitle", "SpFirst", "SpLast"]
    ].transform(lambda x: x.ffill().bfill())
    
    df = df[~m].drop_duplicates()
    
    print(df)
    

    印刷:

        ID Position Title First Last SpTitle SpFirst SpLast     Address  Value1  Value2  Value3
    0  456      HoH   Mr.  John  Doe    Mrs.    Jane    Doe  123 street    20.0     NaN    60.0
    2  789      HoH  Mrs.  Jane  Doe     Mr.    John    Doe    456 road   500.0   710.0   930.0
    

    【讨论】:

    • 这是组合两行和求和值,但 SpTile、SpFirst 和 SpLast 输出空白。有趣的是在最后一列位置放置一列SpLastName2,并用正确的值填充。我已经用我的代码更新了我的问题。
    【解决方案2】:

    您可以在 ID 上的 groupby 之后对列进行不同的聚合,最后将带有 spouses 的行的值填充到聚合输出中。

    df = df.set_index('ID')
    spouses = df.loc[df['Position'].eq('Spouse'), ['Title', 'First', 'Last']].values
    agg_dict = {col : 'sum' if col in ['Value1', 'Value2', 'Value3'] else 'first' for col in df.columns.tolist()}
    
    out = df.groupby(level=0).agg(agg_dict).reset_index()
    out.loc[:, ['SpTitle', 'SpFirst', 'SpLast']] = spouses
    
    print(out)
    

    输出:

        ID Position Title First Last SpTitle SpFirst SpLast     Address  Value1  Value2  Value3
    0  456      HoH   Mr.  John  Doe    Mrs.    Jane    Doe  123 street    20.0     0.0      60
    1  789      HoH  Mrs.  Jane  Doe     Mr.    John    Doe    456 road   500.0   710.0     930
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-20
      • 2022-11-27
      • 1970-01-01
      • 2022-11-05
      • 2021-02-23
      • 1970-01-01
      • 2015-07-20
      • 2021-10-30
      相关资源
      最近更新 更多