我正在寻找最有效的方法来查找column A
中的True
值是否是自column B
中的上一个True
值以来首次出现的值。
在本例中,预期输出为column C
。
示例1:
df = pd.DataFrame({
'A': [False, False, True, False, True, False, True, False, True],
'B': [True, False, False, False, False, True, False, False, False],
'C': [False, False, True, False, False, False, True, False, False]
})
A | B | C||
---|---|---|---|
0 | 错误 | 正确 | 错误|
1 | 错误 | 错误||
2 | 真 | 假 | 真|
3 | 错误 | 错误||
4 | 真 | 假假 | |
5 | 错误 | True | 错误|
6 | 真 | 假 | 真|
7 | 错误 | 错误||
8 | 真 | 假 | 假
您可以对列"的累积和使用groupby
运算;B";按照您描述的方式对数据帧进行分组。然后您可以使用CCD_ 7来获得那些第一次出现的每一个都存在于列"中的索引;A";。一旦你有了这些索引,你就可以创建你的新列"C";。
使用CCD_ 8是一个小技巧,因为我们实际上对最大值不感兴趣;A";只有CCD_ 9和CCD_。idxmax
将返回第一次出现的最大值的索引(在这种情况下,是每组中True
的第一次出现(,这是我们特别感兴趣的。
df = pd.DataFrame({
'A': [False, False, True, False, True, False, True, False, True],
'B': [True, False, False, False, False, True, False, False, False],
})
# get a dataframe of the position of the max as well as the max value
indices_df = df["A"].groupby(df["B"].cumsum()).agg(["idxmax", "max"])
# mask to filter out the 0th group
skip_0th = (indices_df.index > 0)
# mask to filter out groups who do not have True as a value
groups_with_true = (indices_df["max"] == True)
# combine masks and retrieve the appropriate index
indices = indices_df.loc[skip_0th & groups_with_true, "idxmax"]
df["C"] = False
df.loc[indices, "C"] = True
print(df)
A B C
0 False True False
1 False False False
2 True False True
3 False False False
4 True False False
5 False True False
6 True False True
7 False False False
8 True False False
更新示例2。
我们可以通过对索引序列进行切片来排除索引为0的任何条目(例如,从1到末尾进行标签切片(来解决此问题。这是因为我们的groupby
操作根据.cumsum
分配基于整数的标签。在示例1中,最小的索引标签将是1(因为列"B"中的第一个值为True(。而在示例2中,最小的索引标签将是0。由于我们不希望0影响我们的结果,我们可以简单地将其从indices
中剥离。
当我们分配";C";在对我们的indices
系列执行切片之后,我们将适当地忽略列"中第一次出现True之前的所有值;B";。
尽管有足够的文本,让我们看看一些代码。
示例1
print(indices)
1 2
2 6
# Slicing here doesn't change anything, since indices does not have
# a value corresponding to label position 0
indices = indices.loc[1:]
print(indices)
1 2
2 6
示例2
print(indices)
0 0
1 3
2 7
# we don't want to include the value from label position 0 in `indices`
# so we can use slicing to remove it
indices = indices.loc[1:]
print(indices)
1 3
2 7
这是一种方法,也许不是最好的方法。
is_occurred = False
def is_first_occurrence_since(column_to_check, column_occurence):
global is_occurred
if is_occurred and column_to_check == True:
is_occurred = False
return True
elif not is_occurred and column_occurence == True:
is_occurred = True
return False
df.apply(lambda row: is_first_occurrence_since(row['A'], row['B']), axis=1)