Pandas 数据框 - lambda 演算和每个系列的最小值

Posted

技术标签:

【中文标题】Pandas 数据框 - lambda 演算和每个系列的最小值【英文标题】:Pandas data frame - lambda calculus and minimum value per series 【发布时间】:2016-01-22 03:31:59 【问题描述】:

我有一个包含 3 列的 csv,count_id、AMV 和时间。

我正在使用 pandas 并将其作为数据框读入。

results= pd.read_csv('./output.csv')

首先,我首先为 count_id 排序数据帧,然后为 AMV 排序。

results_sorted = results.sort_index(by=['count_id','AMV'], ascending=[True, True])

这给了

   count_id   AMV  Hour
0    16012E  4004    14
1    16012E  4026    12
2    16012E  4099    15
3    16012E  4167    11
4    16012E  4239    10
5    16012E  4324    13
6    16012E  4941    16
7    16012E  5088    17
8    16012E  5283     9
9    16012E  5620     8
10   16012E  5946    18
11   16012E  6146     7
12   16012W  3622    10
13   16012W  3904    12
14   16012W  3979    11
15   16012W  4076     9
16   16012W  4189    13
17   16012W  4870    14
18   16012W  4899    18
19   16012W  5107    15
20   16012W  5659     8
21   16012W  6325     7
22   16012W  6460    17
23   16012W  6500    16

我现在想对数据进行一些标准化,以便最终将其绘制在同一个图上。我想做的是找到每个系列的 AMV 的最小值(count_id),然后从给定的 AMV 中减去这个最小值。这会给我一个新列 AMV_norm。

看起来像:

   count_id   AMV  Hour  AMV_norm
0    16012E  4004    14         0
1    16012E  4026    12        22
2    16012E  4099    15        95
3    16012E  4167    11       163
4    16012E  4239    10       235
5    16012E  4324    13       320
6    16012E  4941    16       937
7    16012E  5088    17      1084
8    16012E  5283     9      1279
9    16012E  5620     8      1616
10   16012E  5946    18      1942
11   16012E  6146     7      2142
12   16012W  3622    10         0
13   16012W  3904    12       282
14   16012W  3979    11       357
15   16012W  4076     9       454
16   16012W  4189    13       567
17   16012W  4870    14      1248
18   16012W  4899    18      1277
19   16012W  5107    15      1485
20   16012W  5659     8      2037
21   16012W  6325     7      2703
22   16012W  6460    17      2838
23   16012W  6500    16      2878

如何定义找到每个系列的最小 AMV 值而不是总体 AMV 最小值的函数?它看起来像这样:

def minimum_series_value(AMV):
    return AMV.argmin()

然后我需要创建一个新列并使用 lambda 函数填充该行。我知道它看起来像这样:

results_sorted['AMV_norm'] = results_sorted.apply(lambda row:results_sorted(row['AMV']))

【问题讨论】:

【参考方案1】:

从变换最小值中减去 AMV 列:

In [11]: df.groupby('count_id')["AMV"].transform('min')
Out[11]:
0     4004
1     4004
2     4004
3     4004
4     4004
...
21    3622
22    3622
23    3622
dtype: int64

In [12]: df["AMV"] - df.groupby('count_id')["AMV"].transform('min')
Out[12]:
0        0
1       22
2       95
3      163
4      235
...
21    2703
22    2838
23    2878
dtype: int64

In [13]: df["AMV_norm"] = df["AMV"] - df.groupby('count_id')["AMV"].transform('min')

【讨论】:

【参考方案2】:

我相信您想在count_id 上进行分组,然后计算该组的当前值与最小值之间的差值。

df['AMV_norm'] = (df.groupby('count_id').AMV
                    .transform(lambda group_series: group_series - np.min(group_series)))

>>> df
   count_id   AMV  Hour  AMV_norm
0    16012E  4004    14         0
1    16012E  4026    12        22
2    16012E  4099    15        95
3    16012E  4167    11       163
4    16012E  4239    10       235
5    16012E  4324    13       320
6    16012E  4941    16       937
7    16012E  5088    17      1084
8    16012E  5283     9      1279
9    16012E  5620     8      1616
10   16012E  5946    18      1942
11   16012E  6146     7      2142
12   16012W  3622    10         0
13   16012W  3904    12       282
14   16012W  3979    11       357
15   16012W  4076     9       454
16   16012W  4189    13       567
17   16012W  4870    14      1248
18   16012W  4899    18      1277
19   16012W  5107    15      1485
20   16012W  5659     8      2037
21   16012W  6325     7      2703
22   16012W  6460    17      2838
23   16012W  6500    16      2878

编辑: @AndyHayden 的方法稍微快一些:

%timeit df["AMV"] - df.groupby('count_id')["AMV"].transform('min')
1000 loops, best of 3: 736 µs per loop

%timeit df.groupby('count_id').AMV.transform(lambda x: x - np.min(x))
1000 loops, best of 3: 804 µs per loop

%timeit df.groupby('count_id').AMV.apply(lambda x: x - np.min(x))
1000 loops, best of 3: 1.32 ms per loop

【讨论】:

在转换中使用返回 Series 的 lambda 似乎很奇怪! (而不是使用应用。) 我猜他们使用相同的路径,但是 transform 通常意味着一个值分布在组上(例如 transform('min')),而 apply 意味着组可以返回任何东西。但你知道我不确定,这是我的理解。 有趣,谢谢。我更喜欢使用 lambda,但正如你所说,安迪的反应更快。感谢您的努力!

以上是关于Pandas 数据框 - lambda 演算和每个系列的最小值的主要内容,如果未能解决你的问题,请参考以下文章

λ演算 (Lambda Calculus) 一 : 定义与函数式编程

如何将 lambda 函数正确应用到 pandas 数据框列

Lambda表达式

在 Pandas 数据框中的不同列上使用 lambda if 条件

Pandas 中的非标准化数据框

是否可以有效地评估 lambda 演算项?