【问题标题】:Groupby selecting certain columns通过选择某些列进行分组
【发布时间】:2022-01-05 01:29:05
【问题描述】:

我按照这里的例子:(https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html#flexible-apply)

数据:

df = pd.DataFrame(
    {
        "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
        "B": ["one", "one", "two", "three", "two", "two", "one", "three"],
        "C": np.random.randn(8),
        "D": np.random.randn(8),
    }
)

按“A”分组,但在“C”列上选择,然后执行应用

grouped = df.groupby('A')['C']

def f(group):
    return pd.DataFrame({'original': group,
                         'demeaned': group - group.mean()})

grouped.apply(f)

一切正常,但是当我尝试使用 groupby'A' 并选择列 'C' 和 'D' 时,我无法成功:

grouped = df.groupby('A')[['C', 'D']]

for name, val in grouped:
    print(name)
    print(val)

grouped.apply(f)

那么我在这里做错了什么?

谢谢 范

【问题讨论】:

  • 你有错误吗?始终将完整的错误消息(从“Traceback”一词开始)作为文本(不是屏幕截图,不是链接到外部门户)有问题(不在 cmets 中)。还有其他有用的信息。
  • 对于单列,它给出pandas.Series,但对于许多列,它给出pandas.DataFrame - 所以它需要在f() 中进行更改 - 比如'original_C': group['C'], 'original_D': group['D'], ...

标签: python pandas dataframe pandas-groupby


【解决方案1】:

当您获得单列 (['C']) 时,它会给出 pandas.Series,但是当您获得多列 ([ ['C', 'D'] ]) 时,它会给出 pandas.DataFrame - 这需要 f() 中的不同代码

可能是

grouped = df.groupby('A')[['C', 'D']]

def f(group):
    return pd.DataFrame({
                'original_C': group['C'],
                'original_D': group['D'],
                'demeaned_C': group['C'] - group['C'].mean(),
                'demeaned_D': group['D'] - group['D'].mean(),
           })

grouped.apply(f)

结果:

   original_C  original_D  demeaned_C  demeaned_D
0   -0.122789    0.216775   -0.611724    1.085802
1   -0.500153    0.912777   -0.293509    0.210248
2    0.875879   -1.582470    0.386944   -0.713443
3   -0.250717    1.770375   -0.044073    1.067846
4    1.261891    0.177318    0.772956    1.046345
5    0.130939   -0.575565    0.337582   -1.278094
6   -1.121481   -0.964481   -1.610417   -0.095454
7    1.551176   -2.192277    1.062241   -1.323250

因为你已经有了两列DataFrame,所以你也可以把它写得更短,而不用转换成pd.DataFrame()

def f(group):
    group[['demeaned_C', 'demeaned_D']] = group - group.mean()

    return group

或更通用

def f(group):
    for col in group.columns:
        group[f'demeaned_{col}'] = group[col] - group[col].mean()

    return group

顺便说一句:

如果您使用[ ['C'] ] 而不是['C'],那么您也会得到DataFrame 而不是Series,您可以使用最新版本的f()

【讨论】:

  • 我没有测试这个,但我认为你也可以这样做return group.sub(group.mean()).add_prefix('demeaned_')
  • @tdy 我测试了它 - 它给出了正确的值,但 add_prefix() 创建了具有 2 个级别的新索引的 DataFrame - 第一级使用来自 A 列的值 "foo", "bar",第二级使用原始索引.这会将行以不同的顺序排列 - 首先是foo 的所有行,然后是bar 的所有行。我使用.rename(columns=lambda name:f'demeaned_{name}') 得到的结果相同。目前我不知道如何更改它。
猜你喜欢
  • 1970-01-01
  • 2017-05-24
  • 1970-01-01
  • 2019-01-30
  • 2016-06-03
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 1970-01-01
相关资源
最近更新 更多