我正在使用Pandas DataFrames。我正在寻找标识A和B都为True的所有行,然后在C列中表示该交点另一侧的所有点,其中只有A或B仍然为真,而另一侧不是。例如:
A B C
0 False False False
1 True False True
2 True True True
3 True True True
4 False True True
5 False False False
6 True False False
7 True False False
我可以很容易地找到直接重叠的部分:
df.loc[(df['A'] == True) & (df['B'] == True), 'C'] = True
...但是,这没有考虑重叠的需求。
我考虑过以这种方式创建列'C',然后将每列分组:
grp_a = df.loc[(df['A'] == True), 'A'].groupby(df['A'].astype('int').diff.ne(0).cumsum())
grp_b = df.loc[(df['A'] == True), 'A'].groupby(df['A'].astype('int').diff.ne(0).cumsum())
grp_c = df.loc[(df['A'] == True), 'A'].groupby(df['A'].astype('int').diff.ne(0).cumsum())
从那里我想遍历grp_c.indices中的索引并针对它们测试grp_a和grp_b中的索引,找到A和B的最小/最大索引并更新列C。这感觉像是一种获取效率低下的方式到我想要的结果。
想法?
答案 0 :(得分:1)
尝试一下:
#Input df just columns 'A' and 'B'
df = df[['A','B']]
df['C'] = df.assign(C=df.min(1)).groupby((df[['A','B']].max(1) == 0).cumsum())['C']\
.transform('max').mask(df.max(1)==0, False)
print(df)
输出:
A B C
0 False False False
1 True False True
2 True True True
3 True True True
4 False True True
5 False False False
6 True False False
7 True False False
首先,创建带有最小值分配的列“ C”,这是将True关联到C,其中A和B均为True。接下来,使用
df[['A','B']].max(1) == 0
0 True
1 False
2 False
3 False
4 False
5 True
6 False
7 False
dtype: bool
我们可以找到所有记录,其中A和B均为False。然后,我们使用cumsum
创建这些False False记录的计数。允许我们用False False记录创建记录分组,直到下一个False False记录递增为止。
(df[['A','B']].max(1) == 0).cumsum()
0 1
1 1
2 1
3 1
4 1
5 2
6 2
7 2
dtype: int32
通过使用cumsum创建的分组,让数据帧与新分配的列C分组。然后从该组中获取列C的最大值。因此,如果该组具有True True记录,则将True分配给该组中的所有记录。最后,使用mask
将第一个False False记录改回False。
df.assign(C=df.min(1)).groupby((df[['A','B']].max(1) == 0).cumsum())['C']\
.transform('max').mask(df.max(1)==0, False)
0 False
1 True
2 True
3 True
4 True
5 False
6 False
7 False
Name: C, dtype: bool
然后,将该系列分配给df ['C'],以覆盖语句中临时分配的C。
df['C'] = df.assign(C=df.min(1)).groupby((df[['A','B']].max(1) == 0).cumsum())['C']\
.transform('max').mask(df.max(1)==0, False)