Python Pandas:使用Aggregate与Apply来定义新列

All*_*enQ 5 python pandas

假设我有一个像这样的数据帧:

n = 20
dim1 = np.random.randint(1, 3, size=n)
dim2 = np.random.randint(3, 5, size=n)
data1 = np.random.randint(10, 20, size=n)
data2 = np.random.randint(1, 10, size=n)
df = pd.DataFrame({'a': dim1, 'b': dim2 ,'val1': data1, 'val2': data2})
Run Code Online (Sandbox Code Playgroud)

如果我定义一个返回分组的函数:

def h(x):
    if x['val2'].sum() == 0:
        return 0
    else:
        return (x['val1'].sum())*1.0/x['val2'].sum()*1.0
Run Code Online (Sandbox Code Playgroud)

按列之一进行分组并聚合返回结果:

df.groupby(['a']).aggregate(h)['val1']
Run Code Online (Sandbox Code Playgroud)

虽然它将所有现有列转换为所需结果,而不是添加新列

使用聚合时,按两列分组会导致错误:

df.groupby(['a','b']).aggregate(h)['val1']

KeyError: 'val2'
Run Code Online (Sandbox Code Playgroud)

但转换聚合申请似乎有效.

我有两个问题:

  1. 为什么应用工作而不是聚合?
  2. 如果在通过某组键对数据帧进行分组后,我想使用将组值聚合为新列的函数,那么最好的方法是什么?

提前致谢.

And*_*den 0

退一步来说,执行此特定“聚合”的更快方法是仅使用sum (它在 cython 中进行了优化)几次。

\n\n
In [11]: %timeit g.apply(h)\n1000 loops, best of 3: 1.79 ms per loop\n\nIn [12]: %timeit g[\'val1\'].sum() / g[\'val2\'].sum()\n1000 loops, best of 3: 600 \xc2\xb5s per loop\n
Run Code Online (Sandbox Code Playgroud)\n\n

IMO groupby 代码非常复杂,通常通过创建它所看到的值的列表来懒惰地“黑匣子”查看正在发生的事情:

\n\n
def h1(x):\n   a.append(x)\n   return h(x)\na = []\n
Run Code Online (Sandbox Code Playgroud)\n\n

警告:有时此列表中的数据类型不一致(其中pandas 在执行任何计算之前尝试一些不同的操作)...如本示例所示!

\n\n

第二个聚合在每一列上应用时都卡住了,因此该组(这会引发错误):

\n\n
0     10\n4     16\n8     13\n9     17\n17    17\n19    11\nName: val1, dtype: int64\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是 val1 列的子系列,其中 (a, b) = (1, 3)。

\n\n

这很可能是一个错误,在出现这个错误之后,也许它可以尝试其他方法(我怀疑这就是第一个版本起作用的原因,它是特殊情况)...

\n\n

对于那些感兴趣的人,a我得到的是:

\n\n
In [21]: a\nOut[21]: \n[SNDArray([125755456, 131767536,        13,        17,        17,        11]),\n Series([], name: val1, dtype: int64),\n 0     10\n4     16\n8     13\n9     17\n17    17\n19    11\nName: val1, dtype: int64]\n
Run Code Online (Sandbox Code Playgroud)\n\n

我不知道 SNDArray 是怎么回事......

\n