在pandas数据帧中,我想创建一个新列,用于计算当前行之前第4、第8和第12行的列值的平均值。
如下表所示,对于第13行:
第13行(第9行(之前4行的现有列中的值=4
第13行(第5行(之前8行的现有列中的值=6
第13行(第1行(之前12行的现有列中的值=2
4,6,2的平均值为4。因此,第13行的新列=4,对于1-12之间的其余行,新列=楠
我的df中有更多的行,但为了便于说明,我只添加了前13行。
行号 | 现有列 | 新列|
---|---|---|
1 | 2 | NaN |
2 | 4 | NaN |
3 | 3 | NaN |
4 | 1 | NaN |
5 | 6 | NaN |
6 | 4 | NaN |
7 | 8 | NaN |
8 | 2 | NaN |
9 | 4 | NaN |
10 | 9 | NaN |
11 | 2 | NaN |
12 | 4 | NaN |
13 | 3 |
.shift()
是您缺少的部分。我们可以使用它来访问Pandas数据帧中现有行中的前几行。
让我们使用.groupby()
、.apply()
和.shift()
如下:
df['New column'] = df.groupby((df['Row number'] - 1) // 13)['Existing column'].apply(lambda x: (x.shift(4) + x.shift(8) + x.shift(12)) / 3)
这里,通过将行分组在(df['Row number'] - 1) // 13
设置的不同组号下,将行划分为13行的组
然后,在每个组中,我们在列Existing column
上使用.apply()
,并使用.shift()
获得组中前面的第4、第8和第12个条目。
试运行
data = {'Row number' : np.arange(1, 40), 'Existing column': np.arange(11, 50) }
df = pd.DataFrame(data)
print(df)
Row number Existing column
0 1 11
1 2 12
2 3 13
3 4 14
4 5 15
5 6 16
6 7 17
7 8 18
8 9 19
9 10 20
10 11 21
11 12 22
12 13 23
13 14 24
14 15 25
15 16 26
16 17 27
17 18 28
18 19 29
19 20 30
20 21 31
21 22 32
22 23 33
23 24 34
24 25 35
25 26 36
26 27 37
27 28 38
28 29 39
29 30 40
30 31 41
31 32 42
32 33 43
33 34 44
34 35 45
35 36 46
36 37 47
37 38 48
38 39 49
df['New column'] = df.groupby((df['Row number'] - 1) // 13)['Existing column'].apply(lambda x: (x.shift(4) + x.shift(8) + x.shift(12)) / 3)
print(df)
Row number Existing column New column
0 1 11 NaN
1 2 12 NaN
2 3 13 NaN
3 4 14 NaN
4 5 15 NaN
5 6 16 NaN
6 7 17 NaN
7 8 18 NaN
8 9 19 NaN
9 10 20 NaN
10 11 21 NaN
11 12 22 NaN
12 13 23 15.0
13 14 24 NaN
14 15 25 NaN
15 16 26 NaN
16 17 27 NaN
17 18 28 NaN
18 19 29 NaN
19 20 30 NaN
20 21 31 NaN
21 22 32 NaN
22 23 33 NaN
23 24 34 NaN
24 25 35 NaN
25 26 36 28.0
26 27 37 NaN
27 28 38 NaN
28 29 39 NaN
29 30 40 NaN
30 31 41 NaN
31 32 42 NaN
32 33 43 NaN
33 34 44 NaN
34 35 45 NaN
35 36 46 NaN
36 37 47 NaN
37 38 48 NaN
38 39 49 41.0
- 您可以将
rolling
与.apply
一起使用来应用自定义聚合函数 - (4,6,2(的平均值是4,而不是3
>>> (2 + 6 + 4) / 3
4.0
>>> df["New column"] = df["Existing column"].rolling(13).apply(lambda x: x.iloc[[0, 4, 8]].mean())
>>> df
Row number Existing column New column
0 1 2 NaN
1 2 4 NaN
2 3 3 NaN
3 4 1 NaN
4 5 6 NaN
5 6 4 NaN
6 7 8 NaN
7 8 2 NaN
8 9 4 NaN
9 10 9 NaN
10 11 2 NaN
11 12 4 NaN
12 13 3 4.0
分解:
- CCD_ 11:选择";现有列";从数据帧
.rolling(13)
:从前13行开始,我们将在所有数据上移动一个滑动窗口。因此,首先,我们将遇到行0-12,然后是行1-13,然后是2-14,依此类推.apply(...)
:对于前面提到的每个滚动部分,我们将应用一个对每个部分都有效的函数(在这种情况下,我们应用的函数是lambdalambda x: x.iloc[[0, 4, 8]].mean()
:从每个轧制段中提取第0个、第4个和第8个(对应于第1行、第5行和第9行(,并计算并返回这些值的平均值
为了在块(或组(中而不是在滑动窗口中处理数据帧,您可以使用.groupby
方法(而不是.rolling
(应用相同的逻辑。
>>> groups = np.arange(len(df)) // 13 # defines groups as chunks of 13 rows
>>> averages = (
df.groupby(groups)["Existing column"]
.apply(lambda x: x.iloc[[0, 4, 8]].mean())
)
>>> averages.index = (averages.index + 1) * 13 - 1
>>> df["New column"] = averages
>>> df
Row number Existing column New column
0 1 2 NaN
1 2 4 NaN
2 3 3 NaN
3 4 1 NaN
4 5 6 NaN
5 6 4 NaN
6 7 8 NaN
7 8 2 NaN
8 9 4 NaN
9 10 9 NaN
10 11 2 NaN
11 12 4 NaN
12 13 3 4.0
现在分解:
groups = np.arange(len(df))
:创建一个数组,该数组将用于将数据帧分块到组中。这个数组基本上是13个0,后面是13个1,然后是13个2。。。直到数组的长度与数据帧的长度相同。因此,在这种情况下,对于单个块示例,它将仅是一个1300的数组。CCD_ 18根据上面定义的组对数据帧进行分组;现有列";
.apply(lambda x: x.iloc[[0, 4, 8]].mean())
:概念上和以前一样,只是我们应用于每个分组而不是滑动窗口。averages.index = (averages.index + 1) * 12
:这个部分可能看起来有点奇怪。但我们本质上是在确保我们选择的平均值与原始数据集正确一致。在这种情况下,我们希望组0(在averages
系列中用索引值0指定(的平均值与第12行对齐。如果我们有另一个组(组1,我们希望它与原始数据集中的第25行对齐(。所以我们可以用一点数学来做这个变换。df["New column"] = averages
:由于我们已经匹配了我们的指数,熊猫为我们负责这些新值的实际对齐。