如何使用 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

编辑:在我的解决方案 locmask:

之后按条件使用设置 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