这是我的输入:
import pandas as pd
import numpy as np
list1 = [10,79,6,38,4,557,12,220,46,22,45,22]
list2 = [4,3,23,6,234,47,312,2,426,42,435,23]
df = pd.DataFrame({'A' : list1, 'B' : list2}, columns = ['A', 'B'])
df['C'] = np.where (df['A'] > df['B'].shift(-2), 1, np.nan)
print (df)
产生这个输出:
A B C
0 10 4 NaN
1 79 3 1.0
2 6 23 NaN
3 38 6 NaN
4 4 234 NaN
5 557 47 1.0
6 12 312 NaN
7 220 2 1.0
8 46 426 NaN
9 22 42 NaN
10 45 435 NaN
11 22 23 NaN
我需要做的是将“C”列更改为一组连续的三个 1,不重叠。期望的输出是:
A B C
0 10 4 NaN
1 79 3 1.0
2 6 23 1.0
3 38 6 1.0
4 4 234 NaN
5 557 47 1.0
6 12 312 1.0
7 220 2 1.0
8 46 426 NaN
9 22 42 NaN
10 45 435 NaN
11 22 23 NaN
因此,第 2、3 和 6 行从 NaN 变为 1.0。第 7 行已经有一个 1.0,它被忽略了。第 8 行和第 9 行需要保留 NaN,因为第 7 行是前一组的最后一个条目。
我不知道是否有更好的方法来构建在创建时执行此操作的“C”列。
我已经尝试了多个版本的 fillna 和 ffill,但没有一个对我有用。
这看起来很复杂,但我试图用这一行隔离每个 1.0 的行 ID:
print (df.loc[df['C'] == 1])
正确输出的是:
A B C
1 79 3 1.0
5 557 47 1.0
7 220 2 1.0
即使我知道该信息,我也不知道如何从那里继续。
非常感谢您的提前帮助, 大卫
最佳答案
编辑:
更快的版本(感谢 b2002):
ii = df[pd.notnull(df.C)].index
dd = np.diff(ii)
jj = [ii[i] for i in range(1,len(ii)) if dd[i-1] > 2]
jj = [ii[0]] + jj
for ci in jj:
df.C.values[ci:ci+3] = 1.0
首先通过查看 C
列中不为空的点之间的差异,获取所有起点的索引,即所有 1.0 且后面有两个 NaN 的点 (默认包含第一个索引),然后迭代这些索引并使用 loc
更改 C
列的切片:
ii = df[pd.notnull(df.C)].index
dd = np.diff(ii)
jj = [ii[i] for i in range(1,len(ii)) if dd[i-1] > 2]
jj = [ii[0]] + jj
for ci in jj:
df.loc[ci:ci+2,'C'] = 1.0
结果:
A B C
0 10 4 NaN
1 79 3 1.0
2 6 23 1.0
3 38 6 1.0
4 4 234 NaN
5 557 47 1.0
6 12 312 1.0
7 220 2 1.0
8 46 426 NaN
9 22 42 NaN
10 45 435 NaN
11 22 23 NaN
关于python - pandas 仅替换列的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42381812/