【问题标题】:Python pandas groupby multiple columns, creating list of strings but summing numbersPython pandas groupby多列,创建字符串列表但对数字求和
【发布时间】:2018-12-22 14:19:11
【问题描述】:

目前我的数据框看起来类似于:

     ID  Year   Str1     Str2     Value
0    1   2014   high     black    120
1    1   2015   high     blue     20
2    2   2014   medium   red      10
3    2   2014   medium   blue     50
4    3   2015   low      blue     30
5    3   2015   high     blue     .5
6    3   2015   high     red      10

期望:

     ID  Year   Str1        Str2          Value
0    1   2014   high        black         120
1    1   2015   high        blue          20
2    2   2014   medium      red, blue     60
3    3   2015   low, high   blue, red     40.5

尝试按列 ID 和名称进行分组,然后得到数字的总和,但得到字符串列表。如果可以像示例中那样删除重复的字符串,那将很有帮助,但不是必需的。

此操作将对大约 100 个数据帧进行,ID 和年份是唯一可以在每个数据帧中找到的列名。数据框确实略有不同:它们有 value 列、str 列或两者都有。

我已经浏览了很多stackoverflow并尝试过:

df.groupby(['ID', 'Year'], as_index=False).agg(lambda x: x.sum() if x.dtype=='int64' else ', '.join(x))

这给出了错误 DataFrame object has no attribute dtype(这是有道理的,因为按多列分组会返回更多数据帧)。

我也尝试将列一一循环,然后如果列有数字,它会计算总和,否则列一个列表:

for col in df:
    if col in ['ID', 'Year']:
        continue 

    if df[col].dtype.kind == 'i' or df[col].dtype.kind == 'f':
         df = df.groupby(['ID', 'Year'])[col].apply(sum)
    else:
         df = df.groupby(['ID', 'Year'])[col].unique().reset_index()

但是,在第一次执行操作后,它摆脱了所有其他列。

提前致谢。

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    我有一个类似的问题,所以假设我有一个这样的数据,其中包含我想通过电子邮件分组的列并对不同的列执行不同的 agg 函数,所以标准的 groupby 函数不够好。

    无论如何,这是一个虚拟数据集:

        Email            Phone          State
    0   email@gmail.com 123-456-7890    NY
    1   email@gmail.com 321-654-0987    LA
    2   person@gmail.com    123-789-4567    WA
    3   dummy@gmail.com 873-345-3456    MN
    4   dummy@gmail.com 123-345-3456    NY
    5   email@gmail.com 000-000-0000    KY
    

    知道哪个是第一个欺骗项会很有用,因此我们会处理它并忽略其他项。所以首先,我想标记第一个重复项。

    这看起来很复杂,但它的作用是:获取 list of True vals for all the dupes 并与 list of True vals for all first dupes. 进行 AND 运算

    df["first_dupe"] = df.duplicated("Email", keep=False) & ~df.duplicated("Email", keep="first")
    

    然后将此函数应用于数据框:

    def combine_rows(row, key="Email", cols_to_combine=["Phone", "State"]):
        """takes in a row, looks at the key column
            if its the first dupe, combines the data in cols_to_combine with the other rows with same key
            needs a dataframe with a bool column first_dupe with True if the row is the first dupe"""
    
        if row["first_dupe"] == True:
            # making a df of dupes item
            dupes = df[df[key]==row[key]]
    
            for i, dupe_row in dupes.iloc[1:].iterrows():   # skipping the first row, since thats our first_dupe
                for col in cols_to_combine:
                    row[col] += ", " + dupe_row[col]
            # make sure first_dupe doesn't get processed again
            row.first_dupe = False  
        return row
    
    df = df.apply(combine_rows, axis=1, result_type=None)
    

    您可以修改组合行功能以对不同的列执行不同的操作。

    【讨论】:

      【解决方案2】:

      您需要检查numeric 列,例如this solution:

      df = (df.groupby(['ID', 'Year'], as_index=False)
             .agg(lambda x: x.sum() if np.issubdtype(x.dtype, np.number) else ', '.join(x)))
      print (df)
         ID  Year             Str1             Str2  Value
      0   1  2014             high            black  120.0
      1   1  2015             high             blue   20.0
      2   2  2014   medium, medium        red, blue   60.0
      3   3  2015  low, high, high  blue, blue, red   40.5
      

      from pandas.api.types import is_numeric_dtype
      
      df = (df.groupby(['ID', 'Year'], as_index=False)
              .agg(lambda x: x.sum() if is_numeric_dtype(x) else ', '.join(x)))
      

      【讨论】:

      • 如果有人遇到奇怪的行为,而不是获得正确的列表/总和,您会获得每行的列名列表,您可能在数据中有 NaN 值。需要将 NaN 值替换为 df = df.fillna('') 才能正常工作。
      猜你喜欢
      • 2019-02-21
      • 2020-01-15
      • 2015-11-14
      • 2019-09-05
      • 2019-01-03
      • 2022-04-06
      • 1970-01-01
      • 2020-07-22
      • 1970-01-01
      相关资源
      最近更新 更多