【问题标题】:Get mean of numpy array using pandas groupby使用 pandas groupby 获取 numpy 数组的平均值
【发布时间】:2026-02-16 03:40:02
【问题描述】:

我有一个 DataFrame,其中一列是 numpy 数字数组。例如,

import numpy as np
import pandas as pd

df = pd.DataFrame.from_dict({
    'id': [1, 1, 2, 2, 3, 3, 3, 4, 4],
    'data': [np.array([0.43, 0.32, 0.19]),
             np.array([0.41, 0.11, 0.21]),
             np.array([0.94, 0.35, 0.14]),
             np.array([0.78, 0.92, 0.45]),
             np.array([0.32, 0.63, 0.48]),
             np.array([0.17, 0.12, 0.15]),
             np.array([0.54, 0.12, 0.16]),
             np.array([0.48, 0.16, 0.19]),
             np.array([0.14, 0.47, 0.01])]
})

我想groupby id 列并通过获取数组的元素平均值来聚合。首先拆分数组是不可行的,因为它的长度为 300 并且我有 200,000 多行。当我执行df.groupby('id').mean() 时,我收到错误“没有要聚合的数字类型”。我可以使用df['data'].mean() 获得列表的元素平均值,所以我认为应该有一种方法来进行分组平均值。为了澄清,我希望输出是每个 ID 值的数组。结果数组中的每个元素应该是每个组中相应位置的元素值的平均值。在示例中,结果应为:

pd.DataFrame.from_dict({
    'id': [1, 2,3,4],
    'data': [np.array([0.42, 0.215, 0.2]),
             np.array([0.86, 0.635, 0.29500000000000004]),
             np.array([0.3433333333333333, 0.29, 0.26333333333333336]),
             np.array([0.31, 0.315, 0.1])]
})

有人可以建议我如何做到这一点吗?谢谢!

【问题讨论】:

  • 结果应该是什么样的?

标签: python pandas dataframe numpy


【解决方案1】:

意思是两次,一次在数组级别,一次在组级别:

df['data'].map(np.mean).groupby(df['id']).mean().reset_index()

   id      data
0   1  0.278333
1   2  0.596667
2   3  0.298889
3   4  0.241667

根据评论,您可以:

pd.DataFrame(df['data'].tolist(),index=df['id']).mean(level=0).agg(np.array,1)

id
1                                 [0.42, 0.215, 0.2]
2                 [0.86, 0.635, 0.29500000000000004]
3    [0.3433333333333333, 0.29, 0.26333333333333336]
4                                 [0.31, 0.315, 0.1]
dtype: object

或者:

df.groupby("id")['data'].apply(np.mean)

【讨论】:

  • 我应该更清楚一点,我希望输出是一个数组(在示例中长度为 4),其中每个元素是该位置元素的平均值。
  • @AndrejKesely 是的,但在我的版本中有np.mean,刚刚测试和编辑:-) 只意味着给了我DataError: No numeric types to aggregate
  • Using the level keyword in DataFrame and Series aggregations is deprecated 应该是 pd.DataFrame(df['data'].tolist(),index=df['id']).groupby(level=0).mean().agg(np.array,1) 未来版本。
【解决方案2】:

首先,拆分数组可行的,因为您当前的存储需要在 DataFrame 中存储一个包含所有值的复杂对象。这将比简单存储平面二维数组占用更多空间

# Your current memory usage
df.memory_usage(deep=True).sum()
1352

# Create a new DataFrame (really just overwrite `df` but keep separate for illustration)
df1 = pd.concat([df['id'], pd.DataFrame(df['data'].tolist())], 1)
#   id     0     1     2
#0   1  0.43  0.32  0.19
#1   1  0.41  0.11  0.21
#2   2  0.94  0.35  0.14
#3   2  0.78  0.92  0.45
#4   3  0.32  0.63  0.48
#5   3  0.17  0.12  0.15
#6   3  0.54  0.12  0.16
#7   4  0.48  0.16  0.19
#8   4  0.14  0.47  0.01

是的,这看起来更大,但不是在内存方面,它实际上更小。这里的 3 倍系数有点极端,对于具有长数组的较大 DataFrame,它可能会占用 95% 的内存。仍然必须减少。

df1.memory_usage(deep=True).sum()
#416

现在你的聚合是一个普通的groupby + mean,列给出了数组中的位置

df1.groupby('id').mean()
#           0      1         2
#id                           
#1   0.420000  0.215  0.200000
#2   0.860000  0.635  0.295000
#3   0.343333  0.290  0.263333
#4   0.310000  0.315  0.100000

【讨论】:

  • 太棒了。我在这里猜测,但我认为将 id 作为索引而不是 concat 可能会节省一些空间。然后我们可以在分组时参考级别
  • @anky,不确定内存和索引,我从来没有研究过。可悲的是,mean(level=) 已被弃用,因为它们似乎在简化 pandas api 并删除所有冗余方法来执行相同操作(r.i.p.查找:(),所以你仍然需要.groupby('id').mean() (好想id至少可以在索引中)
【解决方案3】:

对数组按平均值分组,其中输出是平均值数组

 df['data'].map(np.array).groupby(df['id']).mean().reset_index()

输出:

   id                                             data
0   1                               [0.42, 0.215, 0.2]
1   2               [0.86, 0.635, 0.29500000000000004]
2   3  [0.3433333333333333, 0.29, 0.26333333333333336]
3   4                               [0.31, 0.315, 0.1]

【讨论】:

  • 你的 pandas 版本是什么,当我在 '1.1.3' 中运行时,我得到了 DataError: No numeric types to aggregate
  • 熊猫==1.3.2 numpy==1.21.2
  • 这很有趣,因为它与我的第一个答案相似,但产生了不同的输出。不能说每个版本的熊猫都在改变什么:/
【解决方案4】:

你总是可以.apply numpy 的意思。

df.groupby('id')['data'].apply(np.mean).apply(np.mean)

# returns:
id
1    0.278333
2    0.596667
3    0.298889
4    0.241667
Name: data, dtype: float64

【讨论】: