ojy*_*ojy 9 python indexing pandas
我想弄清楚何时在pandas DataFrame中使用不同的选择方法.特别是,我正在寻找访问标量值.我经常听到ix一般的推荐.但在pandas文档中
,建议使用at和iat快速标量值访问:
Since indexing with [] must handle a lot of cases (single-label access, slicing, boolean indexing, etc.), it has a bit of overhead in order to figure out what you’re asking for. If you only want to access a scalar value, the fastest way is to use the在and iat methods, which are implemented on all of the data structures.
因此,我认为iat应该更快地获取和设置单个单元格.然而,经过一些测试,我们发现ix读取细胞的速度相当或更快,而iat为细胞分配值要快得多.
这种行为记录在哪里吗?它总是如此,为什么会发生这种情况?是否必须对返回视图或复制执行某些操作?如果有人能对这个问题有所了解并解释建议获取和设置单元格值以及原因,我将不胜感激.
以下是使用pandas的一些测试(版本0.15.2).
为了确保此行为不是此版本的错误,我还在0.11.0上测试了它.我没有提供结果,但趋势完全相同 - ix being much faster for getting, and iat for setting individual cells.
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(1000,2),columns = ['A','B'])
idx = 0
timeit for i in range(1000): df.ix[i,'A'] = 1
timeit for i in range(1000): df.iat[i,idx] = 2
>> 10 loops, best of 3: 92.6 ms per loop
>> 10 loops, best of 3: 21.7 ms per loop
timeit for i in range(1000): tmp = df.ix[i,'A']
timeit for i in range(1000): tmp = df.iat[i,idx]
>> 100 loops, best of 3: 5.31 ms per loop
>> 10 loops, best of 3: 19.4 ms per loop
Run Code Online (Sandbox Code Playgroud)
小智 12
Pandas使用索引类做了一些非常有趣的事情.我不认为我能够描述一种简单的方法来知道使用哪种方法,但我可以对实现提供一些见解.
DataFrame#ix是一个_IXIndexer不声明自己__getitem__或__setitem__.这两种方法很重要,因为它们控制着如何使用Pandas访问值.由于_IXIndexer没有声明这些方法,所以使用了超类_NDFrameIndexer.
关于进一步挖掘_NDFrameIndexer的__getitem__显示它是比较简单的,并且在一些情况下,包装中发现的逻辑get_value.然后__getitem__接近get_value某些情况下的速度.
_NDFrameIndexer这__setitem__是一个不同的故事.起初它看起来很简单,但它调用的第二种方法是_setitem_with_indexer在大多数场景中做了大量的工作.
此信息表明,获取值的调用ix受限get_value于最佳情况,并且使用设置值调用ix将需要核心提交者来解释.
现在DataFrame#iat也是一个_iAtIndexer也没有声明它自己__getitem__或者__setitem__因此回到它的超类_ScalarAccessIndexer的实现.
_ScalarAccessIndexer有一个简单的__getitem__实现,但它需要一个循环,以便将密钥转换为正确的格式.附加循环在调用之前会增加一些额外的处理时间get_value.
_ScalarAccessIndexer还有一个相当简单的__setitem__实现,它set_value在设置值之前转换参数所需的键.
这个信息表明,调用获得值使用iat被限制get_value,以及一个for循环.设置值iat主要受限于调用set_value.因此获取值iat有一点开销,而设置它们的开销较小.
TL; DR
我相信你正在使用Int64Index基于文档的索引的正确访问器,但我不认为这意味着它是最快的.可以直接使用get_value和set_value直接找到最佳性能,但它们需要对Pandas DataFrames的实现方式有更深入的了解.
笔记
值得注意的是,关于熊猫的文档提到get_value并且set_value已被弃用,我认为这是iget_value相反的.
例子
为了显示使用一些索引器(包括直接调用get_value和set_value)的性能差异,我制作了这个脚本:
example.py:
import timeit
def print_index_speed(stmnt_name, stmnt):
"""
Repeatedly run the statement provided then repeat the process and take the
minimum execution time.
"""
setup = """
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(1000,2),columns = ['A','B'])
idx = 0
"""
minimum_execution_time = min(
timeit.Timer(stmnt, setup=setup).repeat(5, 10))
print("{stmnt_name}: {time}".format(
stmnt_name=stmnt_name,
time=round(minimum_execution_time, 5)))
print_index_speed("set ix", "for i in range(1000): df.ix[i, 'A'] = 1")
print_index_speed("set at", "for i in range(1000): df.at[i, 'A'] = 2")
print_index_speed("set iat", "for i in range(1000): df.iat[i, idx] = 3")
print_index_speed("set loc", "for i in range(1000): df.loc[i, 'A'] = 4")
print_index_speed("set iloc", "for i in range(1000): df.iloc[i, idx] = 5")
print_index_speed(
"set_value scalar",
"for i in range(1000): df.set_value(i, idx, 6, True)")
print_index_speed(
"set_value label",
"for i in range(1000): df.set_value(i, 'A', 7, False)")
print_index_speed("get ix", "for i in range(1000): tmp = df.ix[i, 'A']")
print_index_speed("get at", "for i in range(1000): tmp = df.at[i, 'A']")
print_index_speed("get iat", "for i in range(1000): tmp = df.iat[i, idx]")
print_index_speed("get loc", "for i in range(1000): tmp = df.loc[i, 'A']")
print_index_speed("get iloc", "for i in range(1000): tmp = df.iloc[i, idx]")
print_index_speed(
"get_value scalar",
"for i in range(1000): tmp = df.get_value(i, idx, True)")
print_index_speed(
"get_value label",
"for i in range(1000): tmp = df.get_value(i, 'A', False)")
Run Code Online (Sandbox Code Playgroud)
输出:
set ix: 0.9918
set at: 0.06801
set iat: 0.08606
set loc: 1.04173
set iloc: 1.0021
set_value: 0.0452
**set_value**: 0.03516
get ix: 0.04827
get at: 0.06889
get iat: 0.07813
get loc: 0.8966
get iloc: 0.87484
get_value: 0.04994
**get_value**: 0.03111
Run Code Online (Sandbox Code Playgroud)