我今天观察到,选择两列或更多列的数据帧可能比只选择一列慢得多。
如果我使用loc或iloc选择多个列,并且我使用list传递列名或索引,那么与使用iloc的单个列或多个列选择相比,性能会下降100倍(但没有传递列表)
示例:
df = pd.DataFrame(np.random.randn(10**7,10), columns=list('abcdefghij'))
单列选择:
%%timeit -n 100
df['b']
3.17 µs ± 147 ns per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit -n 100
df.iloc[:,1]
66.7 µs ± 5.95 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%%timeit -n 100
df.loc[:,'b']
44.2 µs ± 10.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
两列选择:
%%timeit -n 10
df[['b', 'c']]
96.4 ms ± 788 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit -n 10
df.loc[:,['b', 'c']]
99.4 ms ± 4.44 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit -n 10
df.iloc[:,[1,2]]
97.6 ms ± 1.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
只有此选择的工作方式与预期相同:[编辑]
%%timeit -n 100
df.iloc[:,1:3]
103 µs ± 17.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
机制上的差异是什么?为什么差异如此之大?
[编辑]:正如@run-out指出的,pd。系列似乎比pd处理得快得多。DataFrame,有人知道为什么会这样吗?
另一方面,它没有解释df.iloc[:,[1,2]]
和df.iloc[:,1:3]
我发现这可能源于numpy。
numpy有两种索引:
根据留档,
高级索引始终返回数据的副本(与返回视图的基本切片不同)。
所以如果你检查一下
a=df.values
%timeit -n2 a[:,0:3]
%timeit -n2 a[:,[0,1,2]]
你有
The slowest run took 5.06 times longer than the fastest. This could mean that an intermediate result is being cached.
1.57 µs ± 1.3 µs per loop (mean ± std. dev. of 7 runs, 2 loops each)
188 ms ± 2.17 ms per loop (mean ± std. dev. of 7 runs, 2 loops each)
与数据帧的行为非常相似
Pandas以Pandas.Series的形式处理单行或列,这将比在DataFrame体系结构中处理更快。
熊猫和熊猫一起工作。系列,当你要求:
%%timeit -n 10
df['b']
2.31 µs ± 1.59 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
但是,我可以通过将同一列放入列表来html" target="_blank">调用该列的数据帧。然后你会得到:
%%timeit -n 10
df[['b']]
90.7 ms ± 1.73 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
从上面可以看出,它的系列性能优于DataFrame。
以下是熊猫如何处理b栏。
type(df['b'])
pandas.core.series.Series
type(df[['b']])
pandas.core.frame.DataFrame
编辑:我在扩展我的答案,因为OP想更深入地了解为什么pd.series和pd.dataframe有更高的速度。同时,这也是一个很好的问题,可以帮助我/我们加深对底层技术工作原理的理解。那些有更多专业知识的人请插话。
首先让我们从numpy开始,因为它是熊猫的一个组成部分。根据pandas和Python for Data Analysis的作者Wes McKinney的说法,numpy的性能优于Python:
This is based partly on performance differences having to do with the
cache hierarchy of the CPU; operations accessing contiguous blocks of memory (e.g.,
summing the rows of a C order array) will generally be the fastest because the mem‐
ory subsystem will buffer the appropriate blocks of memory into the ultrafast L1 or
L2 CPU cache.
让我们看看这个例子的速度差。让我们从数据帧的“b”列创建一个numpy数组。
a = np.array(df['b'])
现在做性能测试:
%%timeit -n 10
a
结果是:
32.5 ns ± 28.2 ns per loop (mean ± std. dev. of 7 runs, 10 loops each)
在2.31µs的pd.series时间内,性能大幅提高。
性能提升的另一个主要原因是numpy索引直接进入numpy C扩展,但是当您索引到一个系列中时,会有很多python内容,这要慢得多。(阅读本文)
让我们看看为什么会这样的问题:
df.iloc[:,1:3]
显著优于:
df.iloc[:,[1,2]]
我们的第一个大线索是不正确的是在下面的代码:
df.iloc[:,1:3] is df.iloc[:,[1,2]]
False
它们给出相同的结果,但是不同的对象。我做了一次深入的研究,试图找出两者的区别。我在互联网上或我的图书馆里找不到这方面的参考资料。
看看源代码,我们可以开始看到一些不同。我指的是index.py。
在类_iLocIndexer我们可以找到一些额外的工作熊猫正在做的列表在一个iloc切片。
在检查输入时,我们立即遇到以下两个差异:
if isinstance(key, slice):
return
vs.
elif is_list_like_indexer(key):
# check that the key does not exceed the maximum size of the index
arr = np.array(key)
l = len(self.obj._get_axis(axis))
if len(arr) and (arr.max() >= l or arr.min() < -l):
raise IndexError("positional indexers are out-of-bounds")
仅仅这一点就足以导致性能下降吗?我不知道。
虽然.loc略有不同,但在使用值列表时,它也会影响性能。查看index.py,查看def _getitem_轴(self,key,axis=None):--
处理列表输入的类索引器(键)的代码段相当长,包括大量开销。它包含以下注释:
# convert various list-like indexers
# to a list of keys
# we will use the *values* of the object
# and NOT the index if its a PandasObject
当然,在处理值或整数列表时,会有足够的额外开销,然后直接对切片进行处理,从而导致处理延迟。
其余的代码超过了我的工资等级。如果有人能看一下并敲响它,那将是最受欢迎的
我只是试图通过整数访问命名的熊猫列。 您可以使用按位置选择行。 但是如何通过整数选择列呢? 我的数据框:
问题内容: 我有以下数据(2列4行): 我正在尝试将列合并为一列,看起来像这样(1列,8行): 我使用的熊猫数据框,并使用不同的功能,但没有成功(试过,等)。非常感激任何的帮助! 问题答案: 更新资料 熊猫为此有一个内置的方法,它可以根据您的意愿看到其他答案。 这是我很多年前才知道的第一个答案:
问题内容: 如果我有以下数据帧,派生如下: 有没有一种有效的方法“cumsum”行有限制并且每次都有这个限制 已到达,开始新的“cumsum”。在达到每个极限后(不管有多少 rows),则创建一个包含总累计和的行。 下面我创建了一个这样做的函数的例子,但是它非常 速度很慢,尤其是当数据帧变得非常大时。我不喜欢这样,我的朋友 函数是循环的,我正在寻找一种方法使它更快(我猜 没有环路)。 If you
问题内容: 我有一个数据框,其中的一列作为字典。我想将其解包成多列(即,代码,金额为以下Raw列格式的单独列)。以下代码曾经与pandas v0.22(现在是(0.23))一起工作,给出了索引错误: 我在Google / Stack溢出中搜索了数小时,之前提出的其他解决方案均无法正常工作。 原始列格式: 有没有人有什么建议? 谢谢 问题答案: 设定 与 确保先 和 相同的想法,但跳过
...给出一个错误: .../site-packages/pandas/io/parsers . py:1130:dtype warning:列(4,5,7,16)具有混合类型。请在导入时指定dtype选项,或者设置low_memory=False。 为什么选项与相关,为什么可能有帮助?
问题内容: 所以我有一个数据框df1,看起来像下面的样子: 我想按A列分组,然后对B列求和,同时将值保留在C列中。 问题是,当我说df.groupby(’A’)。sum()列C被删除时,返回 当我进行分组和求和时,如何解决这个问题并保留C列? 问题答案: 唯一的方法是将C包含在groupby中(groupby函数可以接受列表)。 试试看: 需要注意的另一件事是,如果需要在聚合后使用df,则还可以使