numpy .agg()在一个数列中是元素式的吗?

e4eetjau  于 2022-12-29  发布在  其他
关注(0)|答案(3)|浏览(122)

如果我们采用以下数列:

s = pd.Series([20, 21, 12],
              index=['London', 'New York', 'Helsinki'])

London      20
New York    21
Helsinki    12

这使我相信它是按元素方式对一个数列进行运算的:

s.agg('{}_Test'.format)

London      20_Test
New York    21_Test
Helsinki    12_Test

但它也可以在序列上生成标量结果,这是有据可查的。

s.agg(np.sum)

53

我相信.agg()的工作原理应该与apply非常相似,但可以同时接收多个函数。
如果我们使用s.apply(np.sum),因为它是元素方面的,不会做任何事情。
我的问题是,.agg()在不进行聚合时是按元素的吗?在进行聚合时不是按元素的吗?
(in s.agg(lambda x: x) x会是我相信的一个系列,但并不总是。)

bvhaajcl

bvhaajcl1#

Series.agg()方法是否能在元素级工作取决于传递给它的函数。
必须在传递给Series或传递给Series.apply时工作。
因此,当您传递一个以Series作为参数的函数(例如np.sum())时,Series.agg()将不会按元素工作,而是通过将传递的函数一次应用于整个Series来进行正确的聚合。
当你传递一个不接受Series作为参数的函数时,Series.agg()将通过把函数传递给Series.apply()来按元素工作,所以在这种情况下不会发生聚合。

hvvq6cgz

hvvq6cgz2#

Series.agg()方法是否能在元素级工作取决于传递给它的函数。
其实这也取决于系列的内容!

ser_n = pd.Series([111.0, 222.0, 333.0])
ser_s = pd.Series(['abc', 'qrt', 'xyz'])
max(ser_n)      # 333.0
max(ser_s)      # xyz
ser_n.agg(max)  # 333.0
ser_s.agg(max)  # xyz

但是如果你传递你自己的函数. agg(),当dtype是字符串时,行为会有所不同:

ser_n.agg(lambda s: max(s))     # 333.0
ser_s.agg(lambda s: max(s))     # Series: [0]:'c'  [1]:'t' [2]:'z'

还有:

','.join(ser_s)         # 'abc,qrt,xyz'
ser_s.agg(','.join)     # Series: [0]:'a,b,c' [1]:'q,r,t' [2]:'x,y,z'

仔细观察调用内部发生的情况:

def func(s):
    print('---call:---')
    print(s, type(s))
    return max(s)
print('---result:---\n', ser_n.agg(func), '\n')
print('---result:---\n', ser_s.agg(func), '\n')

---call:---
111.0 <class 'float'>
---call:---
0    111.0
1    222.0
2    333.0
dtype: float64 <class 'pandas.core.series.Series'>
---result:---
 333.0 

---call:---
abc <class 'str'>
---call:---
qrt <class 'str'>
---call:---
xyz <class 'str'>
---result:---
0    c
1    t
2    z
dtype: object

这就像第一次调用测试数据的类型。如果是数值型的-第二次调用接受整个系列。如果是字符串型的-然后继续元素的方式。非常奇怪的一个未记录的行为!

7cwmlq89

7cwmlq893#

在Pandas中,至少有0.25.3方法aggregate()的行为是基于元素的还是基于整体的,这取决于应用元素的可能性,而不会基于真实的的运行时数据引发异常!看起来,模块文档中也没有对这种奇怪行为的解释。
下面有一段代码可以绕过这个行为。举个例子,我展示了当我们需要计算包括null(和其他N/A)在内的所有元素时的情况,即获取序列的长度。我们可以使用lambda series: len(series)来代替明显但不正确的操作

def agg_len(series: pd.Series) -> int:
    if not isinstance(series, pd.Series):
        raise TypeError('Element-wise behavior is not supposed')
    return len(series)

series.aggregate(agg_len)

顺便说一句,简单的lambda series: len(series)也可能适合你,但前提是你不使用字符串序列或其他加长类型:)

相关问题