pandas .at vs.loc

kg7wmglp  于 2023-08-01  发布在  其他
关注(0)|答案(5)|浏览(144)

我一直在探索如何优化我的代码,并运行了pandas.at方法。根据文件
基于标签的快速标量访问器
与loc类似,at提供基于标签的标量查找。您也可以使用这些索引器进行设置。
所以我做了一些样本:

设置

import pandas as pd
import numpy as np
from string import letters, lowercase, uppercase

lt = list(letters)
lc = list(lowercase)
uc = list(uppercase)

def gdf(rows, cols, seed=None):
    """rows and cols are what you'd pass
    to pd.MultiIndex.from_product()"""
    gmi = pd.MultiIndex.from_product
    df = pd.DataFrame(index=gmi(rows), columns=gmi(cols))
    np.random.seed(seed)
    df.iloc[:, :] = np.random.rand(*df.shape)
    return df

seed = [3, 1415]
df = gdf([lc, uc], [lc, uc], seed)

print df.head().T.head().T

字符串
df看起来像:

a                                        
            A         B         C         D         E
a A  0.444939  0.407554  0.460148  0.465239  0.462691
  B  0.032746  0.485650  0.503892  0.351520  0.061569
  C  0.777350  0.047677  0.250667  0.602878  0.570528
  D  0.927783  0.653868  0.381103  0.959544  0.033253
  E  0.191985  0.304597  0.195106  0.370921  0.631576


让我们使用.at.loc,并确保得到相同的结果

print "using .loc", df.loc[('a', 'A'), ('c', 'C')]
print "using .at ", df.at[('a', 'A'), ('c', 'C')]

using .loc 0.37374090276
using .at  0.37374090276


使用.loc测试速度

%%timeit
df.loc[('a', 'A'), ('c', 'C')]

10000 loops, best of 3: 180 µs per loop


使用.at测试速度

%%timeit
df.at[('a', 'A'), ('c', 'C')]

The slowest run took 6.11 times longer than the fastest. This could mean that an intermediate result is being cached.
100000 loops, best of 3: 8 µs per loop


这似乎是一个巨大的速度增长。即使在缓存阶段,6.11 * 8也比180快得多

提问

.at有哪些限制?我有动力去使用它。文档说它类似于.loc,但它的行为并不相似。范例:

# small df
sdf = gdf([lc[:2]], [uc[:2]], seed)

print sdf.loc[:, :]

          A         B
a  0.444939  0.407554
b  0.460148  0.465239


其中print sdf.at[:, :]导致TypeError: unhashable type
所以显然不一样,即使意图相似。
也就是说,谁能提供关于.at方法能做什么和不能做什么的指导?

h22fl7wq

h22fl7wq1#

更新:df.get_value从0.21.0版本起已弃用。使用df.atdf.iat是推荐的方法。
df.at一次只能访问一个值。
df.loc可以选择多个行和/或列。
请注意,还有df.get_value,它在访问单个值时可能更快:

In [25]: %timeit df.loc[('a', 'A'), ('c', 'C')]
10000 loops, best of 3: 187 µs per loop

In [26]: %timeit df.at[('a', 'A'), ('c', 'C')]
100000 loops, best of 3: 8.33 µs per loop

In [35]: %timeit df.get_value(('a', 'A'), ('c', 'C'))
100000 loops, best of 3: 3.62 µs per loop

字符串
在底层,df.at[...]调用df.get_value,但它也对键进行一些类型检查。

5fjcxozz

5fjcxozz2#

当你问到.at的局限性时,我最近遇到了一件事(使用pandas 0.22)。让我们使用the documentation的例子:

df = pd.DataFrame([[0, 2, 3], [0, 4, 1], [10, 20, 30]], index=[4, 5, 6], columns=['A', 'B', 'C'])
df2 = df.copy()

    A   B   C
4   0   2   3
5   0   4   1
6  10  20  30

字符串
如果我现在知道了

df.at[4, 'B'] = 100


结果看起来和预期一样

A    B   C
4   0  100   3
5   0    4   1
6  10   20  30


然而,当我尝试做

df.at[4, 'C'] = 10.05

似乎.at试图保存数据类型(这里:int

A    B   C
4   0  100  10
5   0    4   1
6  10   20  30


这似乎是.loc的区别:

df2.loc[4, 'C'] = 10.05


产生所需的

A   B      C
4   0   2  10.05
5   0   4   1.00
6  10  20  30.00


上面例子中的风险在于它悄无声息地发生(从floatint的转换)。当你尝试使用字符串时,它会抛出一个错误:

df.at[5, 'A'] = 'a_string'


ValueError:invalid literal for int()with base 10:'a_string'
但是,如果使用一个字符串int()实际上起作用,如注解中的@n1k31t4所述,它将工作。

df.at[5, 'A'] = '123'

     A   B   C
4    0   2   3
5  123   4   1
6   10  20  30

rqmkfv5c

rqmkfv5c3#

在上面的基础上,at函数的Pandas documentation声明:
访问行/列标签对的单个值。
与loc类似,都提供基于标签的查找。如果只需要获取或设置DataFrame或Series中的单个值,请使用at。
对于设定数据locat是相似的,例如:

df = pd.DataFrame({'A': [1,2,3], 'B': [11,22,33]}, index=[0,0,1])

字符串
locat将产生相同的结果

df.at[0, 'A'] = [101,102]
df.loc[0, 'A'] = [101,102]

    A   B
0   101 11
0   102 22
1   3   33

df.at[0, 'A'] = 103
df.loc[0, 'A'] = 103

    A   B
0   103 11
0   103 22
1   3   33


此外,对于访问单个值,两者是相同的

df.loc[1, 'A']   # returns a single value (<class 'numpy.int64'>)
df.at[1, 'A']    # returns a single value (<class 'numpy.int64'>)

3


但是,当匹配多个值时,loc将从DataFrame返回一组行/列,而at将返回一个值数组

df.loc[0, 'A']  # returns a Series (<class 'pandas.core.series.Series'>)

0    103
0    103
Name: A, dtype: int64

df.at[0, 'A']   # returns array of values (<class 'numpy.ndarray'>)

array([103, 103])


更重要的是,loc可以用于匹配一组行/列,并且只能给出一个索引,而at必须接收列

df.loc[0]  # returns a DataFrame view (<class 'pandas.core.frame.DataFrame'>)

    A   B
0   103 11
0   103 22

# df.at[0]  # ERROR: must receive column

bwntbbo3

bwntbbo34#

.loc相比,.at是一种优化的数据访问方法。
Dataframe 的.loc选择由其参数中给定的indexed_rows和labeled_columns定位的所有元素。相反,.at选择位于给定indexed_row和labeled_column的 Dataframe 的特定元素。
此外,.at接受一行和一列作为输入参数,而.loc可以接受多行和多列。使用.at的输出是单个元素,使用.loc的输出可能是Series或DataFrame。

c9qzyr3d

c9qzyr3d5#

.at的另一个限制是.loc接受其他输入(以换取索引),例如条件,而.at不接受:

> df = pd.DataFrame([[1, 2], 
                   [0, 0],
                   ], 
                   columns=["A", "B"])

> df["A"] > 0 # is a pd.Series of bool values

> df.loc[df["A"] > 0, "B"] # provides the first line in this example

> df.at[df["A"] > 0, "B"] # using .at will raise InvalidIndexError

字符串

相关问题