首页 > 解决方案 > 使用 Pandas 的计算 apply & lambda

问题描述

我有一个数据框,其中有一列日期(YYYY/MM/DD 格式)和一个用于风速测量的列。每个日期都有多个与之相关的风速测量值,我想计算每天风速测量值的标准误差。

我使用 pandas 的“groupby”将所有风速分组到它们被拍摄的日期,并计算每天测量的平均值和数量。

要计算标准误差,必须将一天中每个值的平方差与当天值的平均值相加。显然,这些是不同的长度,我无法弄清楚如何使用 lambdas 函数来做到这一点。

有没有更好的方法来解决这个问题?

#calculate daily averages, daily number of measurements, and list of every value from day
average_from_date = df.groupby(['time'])['wind_spd_ms'].mean()
number = df.groupby(['time'])['wind_spd_ms'].count()
values_from_date = df.groupby(['time'])['wind_spd_ms'].apply(list)

#return list of standard errors for each date in the data set
standard_errors = df.groupby(['time'])['wind_spd_ms'].apply(lambda x: (sum((values_from_date - 
average_from_date)**2)/(number-1)))

标签: pythonpandas

解决方案


虽然groupby.GroupBy.sem是计算此值的好方法,因为它是 pandas 中的现成函数,但在某些情况下,您可能需要使用库中不存在的函数计算新列。

应用() + 拉姆达

这是使用“应用 lambda”方法计算新列*的方式:

res1 = df.groupby(['time'])['wind_spd_ms'].apply(lambda x: ((x-np.mean(x))**2)/(len(x)-1))

重要的是要理解,因为df.groupby(['time'])DataFrame(GroupBy) 对象df.groupby(['time'])['wind_spd_ms']是 Series(GroupBy) 对象,apply()因此函数是pd.Series.apply。它接受一个函数作为参数,函数将以 pandas 系列(此处为df.groupby(['time'])['wind_spd_ms'])作为参数调用。现在,如果您获得列表/系列,您已经知道如何计算标准偏差。

apply() + 另一个函数

使用 apply,您不仅限于 lambda,而是参数可以是任何pd.Series作为参数的函数。所以,同样好的解决方案是。

def calculate_std(x):
    ave = np.mean(x)
    return ((x-ave)**2)/(len(x)-1)

res2 = df.groupby(['time'])['wind_spd_ms'].apply(calculate_std)

通过更复杂的计算,这是更易读和更可取的解决方案

不同的替代方案有多快?

有人可能会认为“使用 lambdas 更快”,但如果您自己为函数计时,您会发现使用 lambdas 并没有提高速度:

In [3]: timeit df.groupby(['time'])['wind_spd_ms'].apply(lambda x: ((x-np.mean(x))**2)/(len(x)-1))
3.26 ms ± 358 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [4]: timeit df.groupby(['time'])['wind_spd_ms'].apply(calculate_std)
2.87 ms ± 63.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

另一方面,oli5679sem提到的功能更快

In [5]: timeit df.groupby(['time'])['wind_spd_ms'].sem()
1.33 ms ± 40.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

(尽管如此,库函数并不总是最快的。例如,使用scipy.ndimage.interpolation.shiftfor shift..)


* 这是分组标准偏差的方程(不是分组平均值的标准误差)


推荐阅读