pandas loc vs. iloc vs. at vs. iat?

2024-12-26 08:43:00
admin
原创
128
摘要:问题描述:最近开始从我的安全区(R)扩展到 Python,并且对中的细胞定位/选择有点困惑Pandas。我已经阅读了文档,但我很难理解各种定位/选择选项的实际含义。是否有理由我应该使用.loc或而.iloc不是at,iat反之亦然? 在什么情况下我应该使用哪种方法?注意:未来的读者请注意,这个问题很老了,是在...

问题描述:

最近开始从我的安全区(R)扩展到 Python,并且对中的细胞定位/选择有点困惑Pandas。我已经阅读了文档,但我很难理解各种定位/选择选项的实际含义。

是否有理由我应该使用.loc或而.iloc不是atiat反之亦然? 在什么情况下我应该使用哪种方法?


注意:未来的读者请注意,这个问题很老了,是在 pandas v0.20 之前编写的,当时存在一个名为 的函数.ix。此方法后来被拆分为两个 -lociloc- 以明确区分位置和基于标签的索引。请注意,ix由于行为不一致且难以理解,已停用,并且在当前版本的 pandas(>= 1.0)中不再存在。


解决方案 1:

loc:仅对索引起作用

iloc:对位置起作用

at:获取标量值。这是一个非常快的 loc

iat:获取标量值。这是一个非常快的 iloc

还,

atiat用于访问标量,即数据框中的单个元素,而lociloc用于同时访问多个元素,可能执行矢量化操作。

http://pyciencia.blogspot.com/2015/05/obtener-y-filtrar-datos-de-un-dataframe.html

解决方案 2:

鉴于已弃用pandas 0.20,已更新ix。这不仅演示了如何使用、、、、,loc还演示了如何实现基于位置/标签的混合索引。iloc`atiatset_value`


loc-基于标签

允许您传递 1-D 数组作为索引器。数组可以是索引或列的切片(子集),也可以是长度等于索引或列的布尔数组。

特别注意:当传递标量索引器时,loc可以分配一个以前不存在的新索引或列值。

# label based, but we can use position values
# to get the labels from the index object
df.loc[df.index[2], 'ColName'] = 3

df.loc[df.index[1:3], 'ColName'] = 3

iloc-基于位置

与 类似,loc但使用位置而不是索引值。但是,您不能分配新列或索引。

# position based, but we can get the position
# from the columns object via the `get_loc` method
df.iloc[2, df.columns.get_loc('ColName')] = 3

df.iloc[2, 4] = 3

df.iloc[:3, 2:4] = 3

at-基于标签的

工作方式与标量索引器非常相似loc无法对数组索引器进行操作。 可以!分配新索引和列。

优点loc速度更快。

缺点是不能使用数组作为索引器。

# label based, but we can use position values
# to get the labels from the index object
df.at[df.index[2], 'ColName'] = 3

df.at['C', 'ColName'] = 3

iat-基于位置

工作原理与 类似iloc无法在数组索引器中工作。 不能!分配新索引和列。

优点iloc速度更快。

缺点是不能使用数组作为索引器。

# position based, but we can get the position
# from the columns object via the `get_loc` method
IBM.iat[2, IBM.columns.get_loc('PNL')] = 3

set_value-基于标签的

工作原理与标量索引器非常相似loc无法对数组索引器进行操作。 可以!分配新索引和列

优点超级快,因为开销很少!

缺点开销很少,因为pandas没有进行大量安全检查。 使用风险自负。此外,这不适合公众使用。

# label based, but we can use position values
# to get the labels from the index object
df.set_value(df.index[2], 'ColName', 3)

set_valuewithtakable=True -基于位置

工作原理与 类似iloc无法在数组索引器中工作。 不能!分配新索引和列。

优点超级快,因为开销很少!

缺点开销很少,因为pandas没有进行大量安全检查。 使用风险自负。此外,这不适合公众使用。

# position based, but we can get the position
# from the columns object via the `get_loc` method
df.set_value(2, df.columns.get_loc('ColName'), 3, takable=True)

解决方案 3:

Pandas 从 DataFrame 中进行选择的主要方式有两种。

  • 标签

  • 整数位置

文档使用术语“位置”来指代整数位置。我不喜欢这个术语,因为我觉得它令人困惑。整数位置更具描述性,并且正是所代表.iloc的。这里的关键词是INTEGER - 按整数位置选择时必须使用整数。

在显示摘要之前,让我们先确保......

.ix 已弃用且含义模糊,不应使用

Pandas有三个主要索引器。我们有索引运算符本身(括号[])、.loc.iloc。让我们总结一下:

  • []- 主要选择列的子集,但也可以选择行。不能同时选择行和列。

  • .loc- 仅按标签选择行和列的子集

  • .iloc- 仅按整数位置选择行和列的子集

我几乎从不使用它们.at.iat因为它们没有增加任何额外的功能,而且性能提升很小。除非你的应用程序对时间非常敏感,否则我不建议使用它们。无论如何,我们有它们的摘要:

  • .at仅通过标签选择 DataFrame 中的单个标量值

  • .iat仅按整数位置选择 DataFrame 中的单个标量值

除了通过标签和整数位置进行选择之外,还存在布尔选择(也称为布尔索引)


下面的示例解释了.loc.iloc、布尔选择和.at.iat

我们首先关注.loc和之间的.iloc差异。在讨论差异之前,重要的是要了解 DataFrames 具有帮助识别每列和每行的标签。让我们看一个示例 DataFrame:

df = pd.DataFrame({'age':[30, 2, 12, 4, 32, 33, 69],
                   'color':['blue', 'green', 'red', 'white', 'gray', 'black', 'red'],
                   'food':['Steak', 'Lamb', 'Mango', 'Apple', 'Cheese', 'Melon', 'Beans'],
                   'height':[165, 70, 120, 80, 180, 172, 150],
                   'score':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2],
                   'state':['NY', 'TX', 'FL', 'AL', 'AK', 'TX', 'TX']
                   },
                  index=['Jane', 'Nick', 'Aaron', 'Penelope', 'Dean', 'Christina', 'Cornelia'])

在此处输入图片描述

所有粗体字都是标签。标签 、、agecolorfood用于列。其他标签 、、、、、height用作行的标签。这些行标签统称为索引score`stateJaneNickAaronPenelopeDeanChristina`Cornelia


选择 DataFrame 中特定行的主要方法是使用.loc.iloc索引器。这些索引器中的每一个也可用于同时选择列,但目前只关注行更容易。此外,每个索引器都使用紧跟其名称的一组括号来进行选择。

.loc 仅通过标签选择数据

我们首先讨论.loc索引器,它仅通过索引或列标签选择数据。在我们的示例 DataFrame 中,我们提供了有意义的名称作为索引的值。许多 DataFrame 没有任何有意义的名称,而是默认为从 0 到 n-1 的整数,其中 n 是 DataFrame 的长度(行数)。

您可以使用多种不同的输入.loc,其中三种是

  • 字符串

  • 字符串列表

  • 使用字符串作为起始值和终止值的切片符号

使用 .loc 和字符串选择一行

要选择单行数据,请将索引标签放在后面的括号内.loc

df.loc['Penelope']

这将以 Series 形式返回数据行

age           4
color     white
food      Apple
height       80
score       3.3
state        AL
Name: Penelope, dtype: object

使用 .loc 和字符串列表选择多行

df.loc[['Cornelia', 'Jane', 'Dean']]

这将返回一个 DataFrame,其行按照列表中指定的顺序排列:

在此处输入图片描述

使用带有切片符号的 .loc 选择多行

切片符号由起始、终止和步长值定义。按标签切片时,pandas 在返回中包含终止值。以下切片从 Aaron 到 Dean(含)。其步长未明确定义,但默认为 1。

df.loc['Aaron':'Dean']

在此处输入图片描述

复杂切片可以采用与 Python 列表相同的方式进行。

.iloc 仅按整数位置选择数据

现在让我们转到.iloc。DataFrame 中的每一行和每一列数据都有一个整数位置来定义它。这是在输出中直观显示的标签的补充。整数位置只是从顶部/左侧开始的行数/列数,从 0 开始。

您可以使用多种不同的输入.iloc,其中三种是

  • 一个整数

  • 整数列表

  • 使用整数作为起始值和终止值的切片符号

使用 .iloc 和整数选择一行

df.iloc[4]

这将以 Series 形式返回第 5 行(整数位置 4)

age           32
color       gray
food      Cheese
height       180
score        1.8
state         AK
Name: Dean, dtype: object

使用 .iloc 和整数列表选择多行

df.iloc[[2, -2]]

这将返回第三行和倒数第二行的 DataFrame:

在此处输入图片描述

使用 .iloc 和切片符号选择多行

df.iloc[:5:3]

在此处输入图片描述


使用 .loc 和 .iloc 同时选择行和列

两者的一个出色功能.loc/.iloc是它们能够同时选择行和列。在上面的示例中,每次选择都会返回所有列。我们可以选择与行相同的输入类型的列。我们只需用逗号分隔行和列选择即可

例如,我们可以选择行 Jane 和 Dean,仅包含列 height、score 和 state,如下所示:

df.loc[['Jane', 'Dean'], 'height':]

在此处输入图片描述

它使用标签列表表示行,使用切片符号表示列

我们自然可以仅使用整数进行类似的操作.iloc

df.iloc[[1,4], 2]
Nick      Lamb
Dean    Cheese
Name: food, dtype: object

使用标签和整数定位同时选择

.ix用于同时使用标签和整数位置进行选择,这种方法很有用,但有时会造成混淆和歧义,幸运的是,它已被弃用。如果您需要使用标签和整数位置的混合进行选择,则必须同时使用标签或整数位置进行选择。

例如,如果我们想选择行Nick以及Cornelia第 2 列和第 4 列,我们可以.loc通过将整数转换为标签来使用,如下所示:

col_names = df.columns[[2, 4]]
df.loc[['Nick', 'Cornelia'], col_names] 

或者,使用索引方法将索引标签转换为整数get_loc

labels = ['Nick', 'Cornelia']
index_ints = [df.index.get_loc(label) for label in labels]
df.iloc[index_ints, [2, 4]]

布尔选择

.loc 索引器还可以进行布尔选择。例如,如果我们想要查找年龄大于 30 的所有行并仅返回foodscore列,我们可以执行以下操作:

df.loc[df['age'] > 30, ['food', 'score']] 

你可以用它复制这个.iloc,但不能传递布尔系列。你必须将布尔系列转换为 NumPy 数组,如下所示:

df.iloc[(df['age'] > 30).values, [2, 4]] 

选择所有行

可以.loc/.iloc仅用于列选择。您可以使用冒号选择所有行,如下所示:

df.loc[:, 'color':'score':2]

在此处输入图片描述


索引运算符[]也可以切片并选择行和列,但不能同时选择。

大多数人都熟悉 DataFrame 索引运算符的主要用途,即选择列。字符串选择单个列作为 Series,字符串列表选择多个列作为 DataFrame。

df['food']

Jane          Steak
Nick           Lamb
Aaron         Mango
Penelope      Apple
Dean         Cheese
Christina     Melon
Cornelia      Beans
Name: food, dtype: object

使用列表选择多列

df[['food', 'score']]

在此处输入图片描述

人们不太熟悉的是,当使用切片符号时,选择是通过行标签或整数位置进行的。这非常令人困惑,我几乎从未使用过,但它确实有效。

df['Penelope':'Christina'] # slice rows by label

在此处输入图片描述

df[2:6:2] # slice rows by integer location

在此处输入图片描述

选择行时,最好使用显式的索引运算符.loc/.iloc。单独使用索引运算符无法同时选择行和列。

df[3:5, 'color']
TypeError: unhashable type: 'slice'

.at由和选择.iat

使用 选择与.at几乎相同.loc,但它仅选择 DataFrame 中的单个“单元格”。我们通常将此单元格称为标量值。要使用.at,请向其传递用逗号分隔的行和列标签。

df.at['Christina', 'color']
'black'

选择与.iat几乎相同,.iloc但它只选择一个标量值。您必须为行和列位置传递一个整数

df.iat[2, 5]
'FL'

解决方案 4:

df = pd.DataFrame({'A':['a', 'b', 'c'], 'B':[54, 67, 89]}, index=[100, 200, 300])

df

                        A   B
                100     a   54
                200     b   67
                300     c   89
In [19]:    
df.loc[100]

Out[19]:
A     a
B    54
Name: 100, dtype: object

In [20]:    
df.iloc[0]

Out[20]:
A     a
B    54
Name: 100, dtype: object

In [24]:    
df2 = df.set_index([df.index,'A'])
df2

Out[24]:
        B
    A   
100 a   54
200 b   67
300 c   89

In [25]:    
df2.ix[100, 'a']

Out[25]:    
B    54
Name: (100, a), dtype: int64

解决方案 5:

让我们从这个小的 df 开始:

import pandas as pd
import time as tm
import numpy as np
n=10
a=np.arange(0,n**2)
df=pd.DataFrame(a.reshape(n,n))

我们也会有

df
Out[25]: 
        0   1   2   3   4   5   6   7   8   9
    0   0   1   2   3   4   5   6   7   8   9
    1  10  11  12  13  14  15  16  17  18  19
    2  20  21  22  23  24  25  26  27  28  29
    3  30  31  32  33  34  35  36  37  38  39
    4  40  41  42  43  44  45  46  47  48  49
    5  50  51  52  53  54  55  56  57  58  59
    6  60  61  62  63  64  65  66  67  68  69
    7  70  71  72  73  74  75  76  77  78  79
    8  80  81  82  83  84  85  86  87  88  89
    9  90  91  92  93  94  95  96  97  98  99

由此,我们有:

df.iloc[3,3]
Out[33]: 33

df.iat[3,3]
Out[34]: 33

df.iloc[:3,:3]
Out[35]: 
    0   1   2   3
0   0   1   2   3
1  10  11  12  13
2  20  21  22  23
3  30  31  32  33



df.iat[:3,:3]
Traceback (most recent call last):
   ... omissis ...
ValueError: At based indexing on an integer index can only have integer indexers

因此我们不能对子集使用.iat,而只能使用.iloc。

但是让我们尝试从更大的 df 中进行选择,然后检查速度......

# -*- coding: utf-8 -*-
"""
Created on Wed Feb  7 09:58:39 2018

@author: Fabio Pomi
"""

import pandas as pd
import time as tm
import numpy as np
n=1000
a=np.arange(0,n**2)
df=pd.DataFrame(a.reshape(n,n))
t1=tm.time()
for j in df.index:
    for i in df.columns:
        a=df.iloc[j,i]
t2=tm.time()
for j in df.index:
    for i in df.columns:
        a=df.iat[j,i]
t3=tm.time()
loc=t2-t1
at=t3-t2
prc = loc/at *100
print('
loc:%f at:%f prc:%f' %(loc,at,prc))

loc:10.485600 at:7.395423 prc:141.784987

因此,使用 .loc 我们可以管理子集,使用 .at 只能管理单个标量,但 .at 比 .loc 更快

:-)

解决方案 6:

值得注意的是,仅访问一列,.loc大约比以下慢 7-10 倍 []

测试脚本:

import os
import sys
from timeit import timeit

import numpy as np
import pandas as pd


def setup():
    arr = np.arange(0, 10 ** 2)
    return pd.DataFrame(arr.reshape(10, 10))


if __name__ == "__main__":
    print(f"Python: {sys.version}")
    print(f"Numpy: {np.__version__}")
    print(f"Pandas: {pd.__version__}")

    iters = 10000

    print(
        "[] Method:",
        timeit(
            "data = df[0]",
            setup="from __main__ import setup; df = setup()",
            number=iters,
        ),
    )
    print(
        ".loc() Method:",
        timeit(
            "data = df.loc[:, 0]",
            setup="from __main__ import setup; df = setup()",
            number=iters,
        ),
    )

输出:

Python: 3.8.10 (tags/v3.8.10:3d8993a, May  3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)]
Numpy: 1.21.1
Pandas: 1.3.3
[] Method: 0.0923579000000001
.loc() Method: 0.6762988000000001
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1579  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1355  
  信创产品在政府采购中的占比分析随着信息技术的飞速发展以及国家对信息安全重视程度的不断提高,信创产业应运而生并迅速崛起。信创,即信息技术应用创新,旨在实现信息技术领域的自主可控,减少对国外技术的依赖,保障国家信息安全。政府采购作为推动信创产业发展的重要力量,其对信创产品的采购占比情况备受关注。这不仅关系到信创产业的发展前...
信创和国产化的区别   8  
  信创,即信息技术应用创新产业,旨在实现信息技术领域的自主可控,摆脱对国外技术的依赖。近年来,国货国用信创发展势头迅猛,在诸多领域取得了显著成果。这一发展趋势对科技创新产生了深远的推动作用,不仅提升了我国在信息技术领域的自主创新能力,还为经济社会的数字化转型提供了坚实支撑。信创推动核心技术突破信创产业的发展促使企业和科研...
信创工作   9  
  信创技术,即信息技术应用创新产业,旨在实现信息技术领域的自主可控与安全可靠。近年来,信创技术发展迅猛,对中小企业产生了深远的影响,带来了诸多不可忽视的价值。在数字化转型的浪潮中,中小企业面临着激烈的市场竞争和复杂多变的环境,信创技术的出现为它们提供了新的发展机遇和支撑。信创技术对中小企业的影响技术架构变革信创技术促使中...
信创国产化   8  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

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

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

内置subversion和git源码管理

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

免费试用