3列条件为真时获取索引号

Posted

技术标签:

【中文标题】3列条件为真时获取索引号【英文标题】:Get index number when condition is true in 3 columns 【发布时间】:2019-12-26 22:42:32 【问题描述】:

我对 python 中的一些代码有疑问。当在 3 个不同的列中满足条件 TRUE 时,我试图提取第一行的索引。这是我正在使用的数据:

       0       1       2             3           4
0   TRUE    TRUE    TRUE    0.41871395  0.492517879
1   TRUE    TRUE    TRUE    0.409863582 0.519425031
2   TRUE    TRUE    TRUE    0.390077415 0.593127232
3   FALSE   FALSE   FALSE   0.372020631 0.704367199
4   FALSE   FALSE   FALSE   0.373546556 0.810876797
5   FALSE   FALSE   FALSE   0.398876919 0.86855678
6   FALSE   FALSE   FALSE   0.432142094 0.875576037
7   FALSE   FALSE   FALSE   0.454115421 0.863063448
8   FALSE   TRUE    FALSE   0.460676901 0.855739006
9   FALSE   TRUE    FALSE   0.458693197 0.855128636
10  FALSE   FALSE   FALSE   0.459201839 0.856451104
11  FALSE   FALSE   FALSE   0.458693197 0.855739006
12  FALSE   FALSE   FALSE   0.458082827 0.856349376
13  FALSE   FALSE   FALSE   0.456556902 0.856959746
14  TRUE    TRUE    TRUE    0.455946532 0.858180486
15  TRUE    TRUE    TRUE    0.455030976 0.858790857
16  TRUE    TRUE    TRUE    0.454725791 0.858485672
17  FALSE   FALSE   FALSE   0.454420606 0.857875301
18  FALSE   FALSE   FALSE   0.454725791 0.858383943
19  FALSE   TRUE    FALSE   0.453199866 0.856654561
20  FALSE   FALSE   FALSE   0.451979125 0.856349376
21  FALSE   FALSE   FALSE   0.45167394  0.856959746
22  FALSE   FALSE   FALSE   0.451775669 0.857570116
23  FALSE   FALSE   FALSE   0.45106357  0.857264931
24  TRUE    TRUE    TRUE    0.450758385 0.856654561
25  TRUE    TRUE    TRUE    0.4504532   0.856044191
26  TRUE    TRUE    TRUE    0.449232459 0.856349376
27  TRUE    TRUE    TRUE    0.448316904 0.855535549

只有当有 3 个“真”条件时我才需要获取索引号:

0   
14  
24

谢谢!

【问题讨论】:

TRUEFALSE 是字符串还是布尔值?因为在 python 中,布尔值只有第一个字母大写 -> True & False 将前三列相加,看看它们的总和是否达到 3。 【参考方案1】:

无论您希望检查 True 值的 3 列的位置如何,以下内容都将起作用,并返回一个列表,指示哪些行存在 3 个 True 值:

编辑:

现已更新以更好地符合 OP 的原始要求:

#df.iloc[:,:3] = df.iloc[:,:3].apply(lambda x: str(x) == "TRUE")    # If necessary
s = (df == True).apply(sum, axis=1) == 3
s = s[s.shift() != s]
s.index[s].tolist()

【讨论】:

当然,这里有一些更优雅的答案,但是任何反对者愿意发表评论吗? 如果还有其他布尔列怎么办?我相信您的答案与特定的给定数据框过于耦合 @Itay OP 的原始请求是“在 3 个不同的列中满足条件 TRUE 时”。尽管可以从给定的数据中推断出前 3 列是什么意思,但同样可能问题是关于给定数据帧中每行任意 3 列中的条件为 True 的一般问题。 好吧,你说服了我。 这不会产生预期的输出:[0, 14, 24]【参考方案2】:

根据答案here,类似这样的内容将为满足所有条件的行提供索引列表:

df[(df[0]==True) & (df[1]==True) & (df[2]==True)].index.tolist()

【讨论】:

这不会产生预期的输出:[0, 14, 24] @RickyKim 有正确的答案。我完全跳过了 OP 只想要满足条件的第一组行的索引的部分。我试图想出一种不使用shift() 的方法来使其更具原创性,但除了低效地循环每一行之外,我想不出任何办法。【参考方案3】:

编辑 2:我有一个新的答案来回应一些澄清。

您正在寻找在012 列中包含TRUE 的每一行,但是您想忽略这些不是连续出现的第一行的行。我的答案的第一部分仍然是一样的,我认为您应该创建一个掩码来选择您的 TRUE 三元组行:

condition = df[[0, 1, 2]].all(axis='columns')

但现在我提出了一种可能的方法来过滤掉您想要忽略的行。在TRUE 三联行的连续中不是第一个意味着前一行也满足condition

idx = df[condition].index
ignore = idx.isin(idx + 1)
result = idx[~ignore]

换句话说,忽略索引值是满足condition的索引值的后继的行。

希望这会有所帮助!


保留我的原始答案以保存记录:

我认为通过将其分为两个步骤,您最终会得到最易读的解决方案:

首先,找出您感兴趣的列中all 的值是True 的行:

condition = df[[0, 1, 2]].all(axis='columns')

那么,你感兴趣的索引值就是df[condition].index

编辑:如果像 Benoit 指出的那样,TRUEFALSE 是字符串,那很好,您只需要对第一步进行微调:

condition = (df[[0, 1, 2]] == 'TRUE').all(axis='columns')

【讨论】:

这不会产生预期的输出:[0, 14, 24] 我想我和其他回答者都很困惑,因为您的解释与您的预期答案不符。您说“我正在尝试在 3 个不同的列中满足条件 TRUE 时提取第一行的索引”,在这种情况下,您可以将 df[condition]head 作为您的答案。我现在看到您真正想要的是TRUE 三连串每条条纹的第一行。我会相应地讨论我的回应。 @RickyKim 见 EDIT2【参考方案4】:

我想大家都错过了“提取第一行的索引”部分。一种方法是首先删除连续的重复项,然后获取所有三个都为 True 的索引,这样你就只能得到第一行的真相

df=df[['0', '1', '2']]
df=df[df.shift()!=df].dropna().all(axis=1)
print(df[df].index.tolist())

输出:

[0, 14, 24]

【讨论】:

【参考方案5】:

我在演示数据帧上尝试过这个,它似乎对我有用。



df = pd.DataFrame(data='A':[True,True,True,True,True,False,True,True],'B':[True,True,False,True,True,False,True,True],'C':[True,False,True,True,True,False,True,True])
i =df[(df['A']==True) & (df['B']==True) & (df['C']==True)].index.to_list()

i = [x for x in i if x-1 not in i]

【讨论】:

您可以将列名替换为数据框中的名称【参考方案6】:

如果你的 DataFrame 中的 TRUE 和 FALSE 实际上是布尔值 True 和 False,那么,

#This will look at the first 3 columns and return True if "all" are True else it will return False:

step1 = [all(q) for q in df[[0,1,2]].values]

id = []
cnt = 0
temp_cnt = 0

#this loop finds where the value is true and checks if the next 2 are also true 
#it then appends the count-2 to a list named id, the -2 compensates for the index.
for q in step1:
    if q:
        cnt += 1
        if cnt == 3:
            id.append(temp_cnt - 2)
    else:
        cnt = 0

    temp_cnt += 1


#Then when printing "id" it will return the first index where AT LEAST 3 True values occur in sequence.
id
Out[108]: [0, 14, 24]

【讨论】:

【参考方案7】:

我认为这可以解决问题。不过,作为一般建议,在 pandas 中命名列总是有帮助的。

假设你的 pandas 数据框名为 data:

data[(data[0] == True) & (data[1] == True) & (data[2] == True)].index.values

list(data[(data[0] == True) & (data[1] == True) & (data[2] == True)].index.values)

【讨论】:

以上是关于3列条件为真时获取索引号的主要内容,如果未能解决你的问题,请参考以下文章

使用动态名称记录条件为真时的变量值

Oracle:两个条件都为真时的条件非空约束

当其他可观察对象为真时,从可观察对象中获取项目

当条件为真时,ios 禁用后退按钮是不是是一种良好的用户体验?

当地图的条件为真时,我只需要将结果分配给“值”

仅当在 Android 中单击按钮后条件为真时才启动 Activity