Python Pandas:获取列与特定值匹配的行的索引

2025-02-25 09:07:00
admin
原创
20
摘要:问题描述:给定一个带有“BoolCol”列的 DataFrame,我们想要找到“BoolCol”值 == True 的 DataFrame 的索引我目前有迭代的方法来实现它,效果很好:for i in range(100,3000): if df.iloc[i]['BoolCol']== True: ...

问题描述:

给定一个带有“BoolCol”列的 DataFrame,我们想要找到“BoolCol”值 == True 的 DataFrame 的索引

我目前有迭代的方法来实现它,效果很好:

for i in range(100,3000):
    if df.iloc[i]['BoolCol']== True:
         print i,df.iloc[i]['BoolCol']

但这不是正确的 pandas 做法。经过一番研究,我目前使用以下代码:

df[df['BoolCol'] == True].index.tolist()

这个给了我一个索引列表,但是当我通过执行以下操作检查它们时,它们不匹配:

df.iloc[i]['BoolCol']

结果居然是False!!

哪种熊猫方法才是正确的?


解决方案 1:

df.iloc[i]返回ith的行dfi不引用索引标签,i是一个基于 0 的索引。

相反,该属性index返回实际的索引标签,而不是数字行索引:

df.index[df['BoolCol'] == True].tolist()

或者等价地,

df.index[df['BoolCol']].tolist()

通过使用具有非默认索引(不等于行的数字位置)的 DataFrame,您可以清楚地看到差异:

df = pd.DataFrame({'BoolCol': [True, False, False, True, True]},
       index=[10,20,30,40,50])

In [53]: df
Out[53]: 
   BoolCol
10    True
20   False
30   False
40    True
50    True

[5 rows x 1 columns]

In [54]: df.index[df['BoolCol']].tolist()
Out[54]: [10, 40, 50]

如果你想使用索引

In [56]: idx = df.index[df['BoolCol']]

In [57]: idx
Out[57]: Int64Index([10, 40, 50], dtype='int64')

loc然后您可以使用而不是来选择行iloc

In [58]: df.loc[idx]
Out[58]: 
   BoolCol
10    True
40    True
50    True

[3 rows x 1 columns]

请注意,loc也可以接受布尔数组

In [55]: df.loc[df['BoolCol']]
Out[55]: 
   BoolCol
10    True
40    True
50    True

[3 rows x 1 columns]

如果您有一个布尔数组,mask并且需要序数索引值,则可以使用来计算它们np.flatnonzero

In [110]: np.flatnonzero(df['BoolCol'])
Out[112]: array([0, 3, 4])

用于df.iloc按序数索引选择行:

In [113]: df.iloc[np.flatnonzero(df['BoolCol'])]
Out[113]: 
   BoolCol
10    True
40    True
50    True

解决方案 2:

可以使用 numpy where() 函数完成:

import pandas as pd
import numpy as np

In [716]: df = pd.DataFrame({"gene_name": ['SLC45A1', 'NECAP2', 'CLIC4', 'ADC', 'AGBL4'] , "BoolCol": [False, True, False, True, True] },
       index=list("abcde"))

In [717]: df
Out[717]: 
  BoolCol gene_name
a   False   SLC45A1
b    True    NECAP2
c   False     CLIC4
d    True       ADC
e    True     AGBL4

In [718]: np.where(df["BoolCol"] == True)
Out[718]: (array([1, 3, 4]),)

In [719]: select_indices = list(np.where(df["BoolCol"] == True)[0])

In [720]: df.iloc[select_indices]
Out[720]: 
  BoolCol gene_name
b    True    NECAP2
d    True       ADC
e    True     AGBL4

虽然您并不总是需要匹配索引,但如果您需要:

In [796]: df.iloc[select_indices].index
Out[796]: Index([u'b', u'd', u'e'], dtype='object')

In [797]: df.iloc[select_indices].index.tolist()
Out[797]: ['b', 'd', 'e']

解决方案 3:

如果您只想使用数据框对象一次,请使用:

df['BoolCol'].loc[lambda x: x==True].index

解决方案 4:

简单的方法是在过滤之前重置 DataFrame 的索引:

df_reset = df.reset_index()
df_reset[df_reset['BoolCol']].index.tolist()

有点奇怪,但是很快!

解决方案 5:

首先你可以检查query目标列的类型bool (PS:如何使用请查看链接)

df.query('BoolCol')
Out[123]: 
    BoolCol
10     True
40     True
50     True

通过布尔列过滤原始 df 后,我们就可以选择索引。

df=df.query('BoolCol')
df.index
Out[125]: Int64Index([10, 40, 50], dtype='int64')

另外,熊猫有nonzero,我们只需选择行的位置True并使用它来切片DataFrameindex

df.index[df.BoolCol.values.nonzero()[0]]
Out[128]: Int64Index([10, 40, 50], dtype='int64')

解决方案 6:

另一种方法是使用来管道化的pipe()索引BoolCol。就性能而言,它与使用 的规范索引一样高效[]。1

df['BoolCol'].pipe(lambda x: x.index[x])

BoolCol如果实际上是多次比较的结果并且您想使用方法链接将所有方法放入管道中,则这特别有用。

例如,如果您想要获取NumCol值大于 0.5、BoolCol值为 True 并且NumColBoolCol值的乘积大于 0 的行索引,则可以通过计算表达式eval()并调用pipe()结果来执行索引的索引。2

df.eval("NumCol > 0.5 and BoolCol and NumCol * BoolCol >0").pipe(lambda x: x.index[x])

1:以下基准测试使用了一个包含 2000 万行的数据框(平均过滤了一半的行)并检索了它们的索引。pipe()与其他高效选项相比,通过链接的方法效果非常好。

n = 20_000_000
df = pd.DataFrame({'NumCol': np.random.rand(n).astype('float16'), 
                   'BoolCol': np.random.default_rng().choice([True, False], size=n)})

%timeit df.index[df['BoolCol']]
# 181 ms ± 2.47 ms per loop (mean ± std. dev. of 10 runs, 1000 loops each)

%timeit df['BoolCol'].pipe(lambda x: x.index[x])
# 181 ms ± 1.08 ms per loop (mean ± std. dev. of 10 runs, 1000 loops each)

%timeit df['BoolCol'].loc[lambda x: x].index
# 297 ms ± 7.15 ms per loop (mean ± std. dev. of 10 runs, 1000 loops each)

2 :对于按照1 )中相同的方式构建的 20 mil 行数据框,您会发现此处提出的方法是最快的选项。它的性能优于按位运算符链接,因为根据设计,它对eval()大型数据框执行多个操作的速度比矢量化 Python 操作更快,并且它比更节省内存,query()因为与 不同query()eval().pipe(...)它不需要创建切片数据框的副本来获取其索引。

解决方案 7:

我扩展了这个问题,即如何获取所有匹配项的rowcolumn值?value

这是解决方案:

import pandas as pd
import numpy as np


def search_coordinate(df_data: pd.DataFrame, search_set: set) -> list:
    nda_values = df_data.values
    tuple_index = np.where(np.isin(nda_values, [e for e in search_set]))
    return [(row, col, nda_values[row][col]) for row, col in zip(tuple_index[0], tuple_index[1])]


if __name__ == '__main__':
    test_datas = [['cat', 'dog', ''],
                  ['goldfish', '', 'kitten'],
                  ['Puppy', 'hamster', 'mouse']
                  ]
    df_data = pd.DataFrame(test_datas)
    print(df_data)
    result_list = search_coordinate(df_data, {'dog', 'Puppy'})
    print(f"

{'row':<4} {'col':<4} {'name':>10}")
    [print(f"{row:<4} {col:<4} {name:>10}") for row, col, name in result_list]

输出:

          0        1       2
0       cat      dog        
1  goldfish           kitten
2     Puppy  hamster   mouse


row  col        name
0    1           dog
2    0         Puppy

解决方案 8:

对于我们感兴趣的已知索引候选,可以通过不检查整个列的更快方法完成,如下所示:

np.array(index_slice)[np.where(df.loc[index_slice]['column_name'] >= threshold)[0]]

全面比较:

import pandas as pd
import numpy as np

index_slice = list(range(50,150)) # know index location for our inteterest
data = np.zeros(10000)
data[(index_slice)] = np.random.random(len(index_slice))

df = pd.DataFrame(
    {'column_name': data},
)

threshold = 0.5

%%timeit
np.array(index_slice)[np.where(df.loc[index_slice]['column_name'] >= threshold)[0]]
# 600 µs ± 1.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%%timeit
[i for i in index_slice if i in df.index[df['column_name'] >= threshold].tolist()]
# 22.5 ms ± 29.1 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

它的工作方式如下:

# generate Boolean satisfy condition only in sliced column
df.loc[index_slice]['column_name'] >= threshold

# convert Boolean to index, but start from 0 and increment by 1
np.where(...)[0]

# list of index to be sliced
np.array(index_slice)[...]

注意:需要注意的是,由于索引,np.array(index_slice)不能用 代替,但你可以做类似 的事情。我认为如果你只用少量行做一次,那么这是不值得的。df.index`np.where(...)[0]start from 0 and increment by 1df.index[index_slice]`

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1343  
  信创产业的蓬勃发展推动着各行业数字化转型加速,数据库迁移作为其中关键一环,面临诸多挑战。信创数据库迁移旨在将传统数据库平稳过渡到信创环境,以满足自主可控、安全可靠的需求。这一过程涉及技术、业务等多方面因素,稍有不慎就可能出现各种问题,影响业务的正常运行。深入探讨信创数据库迁移过程中的常见问题及解决方案,对于保障迁移工作...
2027年信创国产化   41  
  随着信息技术的飞速发展,信创国产化成为了国家战略的重要组成部分。国产化信创产品名录涵盖了众多领域,其在各个关键应用场景中发挥着重要作用。而信创国产化操作系统作为其中的核心环节,具备五大核心优势,为我国信息技术产业的自主可控发展提供了坚实支撑。关键应用场景之办公领域在办公领域,国产化信创产品有着广泛且深入的应用。如今,越...
国产信创系统   37  
  随着信息技术的飞速发展,信创国产化操作系统在政府部门的推广应用具有重要的战略意义。它不仅关乎国家信息安全,更是推动国内信息技术产业自主创新、实现科技自立自强的关键举措。在当前复杂的国际形势下,政府部门积极推广信创国产化操作系统,对于保障国家政务信息的安全稳定运行,提升信息技术的自主可控能力,具有不可替代的重要作用。推广...
信创产品有哪些   28  
  在企业数字化转型的进程中,信创数据库解决方案的选择至关重要。它不仅关乎企业数据的安全存储与管理,更影响着企业业务的稳定运行与未来发展。合适的信创数据库能够助力企业在复杂多变的市场环境中提升竞争力,保障数据主权与安全。然而,面对市场上众多的信创数据库产品和解决方案,企业往往感到困惑,不知如何做出正确的选择。接下来,我们将...
信创电脑   24  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用