【问题标题】:Python dataframe groupby by dictionary list then sumPython数据帧按字典列表分组然后求和
【发布时间】:2016-10-10 03:33:09
【问题描述】:

我有两个数据框。第一个名为mergedcsv 的格式为: mergedcsv dataframe

名为idgrp_df 的第二个数据帧是字典格式,每个区域ID 都有一个对应字符串ID 的列表。 idgrp_df dataframe - keys with lists

对于mergedcsv 中的每一行(以及idgrp_df 中的相应行),我希望选择mergedcsv 中的列,其中列标签等于该行的idgrp_df 列表。然后对这些特定值的值求和,并将输出添加到 mergecsv 中的列。该函数将遍历 mergecsv 中的所有行(582 行 x 600 列)。

我尝试这样做的代码行是:

mergedcsv['TotRegFlows'] = mergedcsv.groupby([idgrp_df],as_index=False).numbers.apply(lambda x: x.iat[0].sum())

它返回一个ValueError: Grouper for class pandas.core.frame.DataFrame not 1-dimensional.

这与 groupby 的输入数据帧有关。如何访问每行的列表作为 groupby 的输入?

例如,对于 mergecsv 中的第一行,我希望选择标签为 F95RR04F95RR06F95RR15 的列(从 idgrp_df 第一行的列表中读取)。将该行的这些列中的值求和,并将求和值插入TotRegFlows 列。

非常感谢任何关于我如何使用该列表的想法。

编辑:

非常感谢 IanS。您的解决方案很有用。根据此建议修改代码行后,我意识到(如建议的那样)我在两个数据帧中的索引不同步。我测试了索引(mergedcsv 有 'None' 并且 idgrp_df 有 'REG_ID' 列作为索引。我也将 mergecsv 设置为 'REG_ID'。然后意识到 mergecsv 有 582 行(REG_ID 不是唯一的)并且 idgrp_df 有 220行(REG_ID 是唯一的)。因此,我认为我缺少基于 mergecsv 中 REG_ID 索引的 groupby。 我修改了代码如下:

mergedcsv.set_index('REG_ID', inplace=True)
    print mergedcsv.index.name
    print idgrp_df.index.name

    mergedcsvgroup = mergedcsv.groupby('REG_ID')[mergedcsv.columns].apply(lambda y: y.tolist())

    mergedcsvgroup['TotRegFlows'] = mergedcsvgroup.apply(lambda row: row[idgrp_df.loc[row.name]].sum(), axis=1)

我有一个 keyError:'REG_ID'。

欢迎任何进一步的建议。将 groupby 合并到一行中会更有效吗?

我是使用 pandas 并尝试在 python 中积累经验的新手

进一步修正:

没有合并csv的索引:

mergedcsv['TotRegFlows'] = mergedcsv.apply(lambda row: row[idgrp_df.loc[row.name]].groupby('REG_ID').sum(), axis=1)

这会引发 KeyError:(标签 [0] 不在 [索引] 中,u '发生在索引 0')

带有mergedcsv的索引:

mergedcsv.set_index('REG_ID', inplace=True)
columnlist = list(mergedcsv.columns.values)
mergedcsv['TotRegFlows'] = mergedcsv.apply(lambda row: row[idgrp_df.loc[row.name]].groupby('REG_ID')[columnlist].transform().sum(), axis=1)

这会引发 TypeError: ("unhashable type:'list'", u'occurred at index 7')

或者最后分离groupby函数:

columnlist = list(mergedcsv.columns.values)
mergedcsvgroup = mergedcsv.groupby('REG_ID')
mergedcsv['TotRegFlows'] = mergedcsvgroup.apply(lambda row: row[idgrp_df.loc[row.name]].sum())

这会引发 TypeError: unhashable type list。 axis=1 参数不适用于 groupby apply。

有什么想法可以将列表与 apply 函数一起使用吗?我已经探索了应用代码中的元组,但没有任何成功。

非常感谢任何建议。

【问题讨论】:

  • 我的回答是否帮助您解决了问题?随时要求澄清!
  • 谢谢@IanS,您的建议在比较两个数据框时非常有用。我意识到第一个数据帧需要 groupby 。我已经编辑了原始帖子以反映更改。但仍然有列表错误。任何进一步的建议将不胜感激。
  • 第一个关键错误是因为一旦您将REG_ID 设置为索引,该列将被删除,您不能再按它进行分组。你可以这样做(使用groupby(level=0)),但由于REG_ID 不是唯一的,我认为这不是一个好主意。
  • 关于您的第二个和第三个解决方案,您在apply 函数内的行上调用groupby,但由于该行只有一行,所以没有什么可分组的。
  • 最后,您的最后一个解决方案将不起作用,因为 applygroupby 对象的工作方式与 apply 到数据框的工作方式非常不同。在第一种情况下,该函数独立地应用于每个组(即子数据帧),而在第二种情况下,它是逐行应用的。

标签: python list pandas dataframe


【解决方案1】:

如果我理解正确,我有一个简单的解决方案,apply

设置

import pandas as pd

df = pd.DataFrame({'A': [1,2,3], 'B': [4,5,6], 'C': [7,8,9]})
lists = pd.Series([['A', 'B'], ['A', 'C'], ['C']])

解决方案

我应用了一个 lambda 函数,该函数从 lists 系列中获取要求和的列列表:

df.apply(lambda row: row[lists[row.name]].sum(), axis=1)

诀窍在于,当迭代行 (axis=1) 时,row.name 是数据帧 df 的原始索引。我用它来访问lists 系列中的列表。

备注

此解决方案假定两个数据框共享相同的索引,在您包含的屏幕截图中似乎并非如此。你必须解决这个问题。

另外,如果idgrp_df 是一个数据框而不是一个系列,那么您需要使用.loc 访问它的值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 2021-08-18
    相关资源
    最近更新 更多