问题描述
我想对以下 df 进行基于条件的比较。
ID type state value
0 123123 1 LOW 5
2 123123 2 LOW 8
5 123123 2 HIGH 2
7 123123 1 LOW 3
1 123412 2 HIGH 21
6 123412 1 LOW 12
3 234234 2 LOW 5
8 234234 1 LOW 1
4 432424 2 HIGH 9
9 432424 1 HIGH 7
所以我想要做的是检查列状态中的值是否为 LOW 的每一行,如果行中的以下值或之前的值是 HIGH。如果是这样,我想检查行类型中的值是否相同。如果再次满足此条件,我想检查此值之间的差异是否小于 2。如果是,名为 validate 的新列应为真,否则应为假。
总而言之,我正在寻找一种方法来检查这种情况的效率。
我考虑过用 apply 来做,但是我不确定如何检查给定行前后的值。
到目前为止,我只考虑通过遍历数据框来实现,但这应该是非常慢的......所以如果你们中的任何人知道如何解决这个问题,我将不胜感激。
结果应该是这样的:
ID type state value valid
0 123123 1 LOW 5 False
2 123123 2 LOW 4 True
5 123123 2 HIGH 2
7 123123 1 LOW 3 True
1 123412 1 HIGH 21
6 123412 1 LOW 12 False
3 234234 2 LOW 5 False
8 234234 1 LOW 1 False
4 432424 2 HIGH 9
9 432424 1 HIGH 7
这里再次总结了行为真的基于行的条件
- 行之前或之后的状态为 HIGH
- 对于高的行(或者如果两者都适用)然后检查类型是否相同
- 最后检查值之间的差异是否小于 2
解决方法
试试这个 -
df.loc[df.state == 'LOW','valid'] = False
df.loc[(df.state != df.state.shift(-1)) & (df.state == 'LOW'),'valid'] = True
,
使用 shift()
和 diff()
为 above | below
、state
和 type
条件创建 value
掩码。
below = df.state.eq('LOW') & df.state.shift(-1).eq('HIGH') & df.type.shift(-1).eq(df.type) & df.value.diff(-1).abs().le(2)
above = df.state.eq('LOW') & df.state.shift().eq('HIGH') & df.type.shift().eq(df.type) & df.value.diff().abs().le(2)
df.loc[df.state.eq('LOW'),'valid'] = False
df.loc[above | below,'valid'] = True
索引 7 的输出不同,但我不明白为什么您的预期输出显示 True
,因为上面的 type
不同(1 对 2)和低于 value
的不同是 18:
ID type state value valid
0 123123 1 LOW 5 False
2 123123 2 LOW 4 True
5 123123 2 HIGH 2 NaN
7 123123 1 LOW 3 False
1 123412 2 HIGH 21 NaN
6 123412 1 LOW 12 False
3 234234 2 LOW 5 False
8 234234 1 LOW 1 False
4 432424 2 HIGH 9 NaN
9 432424 1 HIGH 7 NaN
,
您可以使用 df.shift 方法并将您的 df 与移位的 df 进行比较。这样就不需要循环了。