找到列值重叠的行的最小值/最大值,创建新列以代表二者的完整范围

时间:2019-02-25 21:53:55

标签: pandas

我正在使用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。这感觉像是一种获取效率低下的方式到我想要的结果。

想法?

1 个答案:

答案 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)