如何使用 pandas 从每组行的列中减去值列表
How to subtract a list of values from a column every each group of rows with pandas
我有一个值列表:
T=['23','22','13','25','33','21','20']
和一个包含 1 列 14 行的文件:
24
25
-9999
0
35
39
40
33
44
45
27
39
35
39
代码:
df - pd.Series(T)
我想每 7 行从文件的列中减去列表 T(即包含 7 行),但忽略带有 -9999 和 0 的值。如何使用 pandas in python?
df.mask(df.isin([-9999, 0]))
预期输出如下:
col new
0 24 1
1 25 3
2 15 0
3 27 0
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
对列表的重复值使用 numpy.tile
,按 df
的长度过滤,转换为整数并减去是最简单和最快的解决方案:
T=('23','22','13','25','33','21','20')
#if there is always 14 rows
#df['new'] = df['col'].sub(np.tile(T,2).astype(int))
#any rows
df['new'] = df['col'].sub(np.tile(T, len(df) // len(T) + 2)[:len(df)].astype(int))
print (df)
col new
0 24 1
1 25 3
2 15 2
3 27 2
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
或者可以使用整数除法 Series
和原始 df.index
之间的索引值对齐:
T=('23','22','13','25','33','21','20')
df.index = df.index % len(T)
df['new'] = df['col'].sub(pd.Series(T).astype(int).loc[df.index])
df = df.reset_index(drop=True)
print (df)
col new
0 24 1
1 25 3
2 15 2
3 27 2
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
或者可以按组减去,这是最慢的解决方案:
f = lambda x: x.sub(np.array(T).astype(int))
df['new'] = df.groupby(df.index // len(T))['col'].transform(f)
print (df)
col new
0 24 1
1 25 3
2 15 2
3 27 2
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
编辑:在我的解决方案 loc
或 mask
:
之后按条件使用设置 0
df.loc[df['col'].isin([-9999, 0]), 'new'] = 0
#alternative
#df['new'] = df['new'].mask(df['col'].isin([-9999, 0]), 0)
print (df)
col new
0 24 1
1 25 3
2 -9999 0
3 0 0
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
我有一个值列表:
T=['23','22','13','25','33','21','20']
和一个包含 1 列 14 行的文件:
24
25
-9999
0
35
39
40
33
44
45
27
39
35
39
代码:
df - pd.Series(T)
我想每 7 行从文件的列中减去列表 T(即包含 7 行),但忽略带有 -9999 和 0 的值。如何使用 pandas in python?
df.mask(df.isin([-9999, 0]))
预期输出如下:
col new
0 24 1
1 25 3
2 15 0
3 27 0
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
对列表的重复值使用 numpy.tile
,按 df
的长度过滤,转换为整数并减去是最简单和最快的解决方案:
T=('23','22','13','25','33','21','20')
#if there is always 14 rows
#df['new'] = df['col'].sub(np.tile(T,2).astype(int))
#any rows
df['new'] = df['col'].sub(np.tile(T, len(df) // len(T) + 2)[:len(df)].astype(int))
print (df)
col new
0 24 1
1 25 3
2 15 2
3 27 2
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
或者可以使用整数除法 Series
和原始 df.index
之间的索引值对齐:
T=('23','22','13','25','33','21','20')
df.index = df.index % len(T)
df['new'] = df['col'].sub(pd.Series(T).astype(int).loc[df.index])
df = df.reset_index(drop=True)
print (df)
col new
0 24 1
1 25 3
2 15 2
3 27 2
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
或者可以按组减去,这是最慢的解决方案:
f = lambda x: x.sub(np.array(T).astype(int))
df['new'] = df.groupby(df.index // len(T))['col'].transform(f)
print (df)
col new
0 24 1
1 25 3
2 15 2
3 27 2
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19
编辑:在我的解决方案 loc
或 mask
:
0
df.loc[df['col'].isin([-9999, 0]), 'new'] = 0
#alternative
#df['new'] = df['new'].mask(df['col'].isin([-9999, 0]), 0)
print (df)
col new
0 24 1
1 25 3
2 -9999 0
3 0 0
4 35 2
5 39 18
6 40 20
7 33 10
8 44 22
9 45 32
10 27 2
11 39 6
12 35 14
13 39 19