反转 pandas DataFrame 的正确方法?

问题描述 投票:0回答:7

这是我的代码:

import pandas as pd

data = pd.DataFrame({'Odd':[1,3,5,6,7,9], 'Even':[0,2,4,6,8,10]})

for i in reversed(data):
    print(data['Odd'], data['Even'])

当我运行此代码时,出现以下错误:

Traceback (most recent call last):
  File "C:\Python33\lib\site-packages\pandas\core\generic.py", line 665, in _get_item_cache
    return cache[item]
KeyError: 5

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\*****\Documents\******\********\****.py", line 5, in <module>
    for i in reversed(data):
  File "C:\Python33\lib\site-packages\pandas\core\frame.py", line 2003, in __getitem__
    return self._get_item_cache(key)
  File "C:\Python33\lib\site-packages\pandas\core\generic.py", line 667, in _get_item_cache
    values = self._data.get(item)
  File "C:\Python33\lib\site-packages\pandas\core\internals.py", line 1656, in get
    _, block = self._find_block(item)
  File "C:\Python33\lib\site-packages\pandas\core\internals.py", line 1936, in _find_block
    self._check_have(item)
  File "C:\Python33\lib\site-packages\pandas\core\internals.py", line 1943, in _check_have
    raise KeyError('no item named %s' % com.pprint_thing(item))
KeyError: 'no item named 5'

为什么我会收到此错误?
我该如何解决这个问题?
正确的反转方法是什么

pandas.DataFrame

python pandas reverse
7个回答
467
投票
data.reindex(index=data.index[::-1])

或者简单地说:

data.iloc[::-1]

将反转你的数据框,如果你想要一个从下到上的

for
循环,你可以这样做:

for idx in reversed(data.index):
    print(idx, data.loc[idx, 'Even'], data.loc[idx, 'Odd'])

for idx in reversed(data.index):
    print(idx, data.Even[idx], data.Odd[idx])

您收到错误,因为

reversed
首先调用
data.__len__()
,返回 6。然后它尝试为
data[j - 1]
中的
j
调用
range(6, 0, -1)
,第一个调用将是
data[5]
;但在 pandas dataframe 中
data[5]
表示第 5 列,并且没有第 5 列,因此会抛出异常。 (参见文档


141
投票

您可以用更简单的方式反转行:

df[::-1]

76
投票

反转 pandas DataFrame 的正确方法是什么?

TL;博士:
df[::-1]

这是反转 DataFrame 的最佳方法,因为 1) 它是恒定的运行时间,即 O(1) 2) 它是单个操作,并且 3) 简洁/可读(假设熟悉切片表示法)。


长版

我发现 ol' 切片技巧

df[::-1]
(或等效的
df.loc[::-1]
1)是反转 DataFrame 的最简洁和惯用的方法。这反映了 python 列表反转语法
lst[::-1]
并且其意图很明确。 使用
loc
语法,您还可以根据需要对列进行切片,因此更加灵活。

处理索引时需要考虑的一些要点:

  • “如果我也想反转索引怎么办?”

    • 你已经完成了。
      df[::-1]
      反转索引和值。
  • “如果我想从结果中删除索引怎么办?”

  • “如果我想保持索引不变(IOW,只反转数据,而不反转索引)怎么办?”

    • 这有点不传统,因为它意味着索引与数据并不真正相关。也许考虑完全删除它?尽管从技术上讲,您所要求的可以使用
      df[:] = df[::-1]
      (它创建对
      df
      的就地更新)或
      df.loc[::-1].set_index(df.index)
      (返回副本)来实现。

1:

df.loc[::-1]
df.iloc[::-1]
是等效的,因为切片语法保持不变,无论您是按位置 (
iloc
) 还是按标签 (
loc
) 反转。


证据就在布丁中

enter image description here

X轴代表数据集大小。 Y 轴表示反转所需的时间。没有任何方法可以像切片技巧那样缩放,它一直位于图表的底部。 基准测试代码供参考,使用perfplot生成的图。


对其他解决方案的评论

  • df.reindex(index=df.index[::-1])
    显然是一个流行的解决方案,但乍一看,对于不熟悉的读者来说,这段代码“反转 DataFrame”有多明显?此外,这是反转索引,然后使用该中间结果来
    reindex
    ,因此这本质上是一个TWO步骤操作(当它可能只是一个时)。

  • df.sort_index(ascending=False)
    在大多数情况下,如果您有一个简单的范围索引,则可能会起作用,但这假设您的索引按升序排序,因此不能很好地概括。

  • 请不要使用

    iterrows
    。我看到一些选项建议反向迭代。无论您的用例是什么,都可能有可用的向量化方法,但如果没有,那么您可以使用更合理的方法,例如列表推导式。有关为什么 iterrows 是反模式的更多详细信息,请参阅
    How to iterate over rows in a DataFrame in Pandas


34
投票
现有答案都不会在反转数据帧后重置索引。

为此,请执行以下操作:

data[::-1].reset_index()

这里有一个

实用函数,它也会删除旧的索引列,根据@Tim的评论:

def reset_my_index(df): res = df[::-1].reset_index(drop=True) return(res)

只需

将数据帧传递到函数中


10
投票
处理排序范围索引时执行此操作的一种方法是:

data = data.sort_index(ascending=False)
这种方法的优点是 (1) 是单行,(2) 不需要实用函数,最重要的是 (3) 

实际上不会更改数据框中的任何数据。

警告:这通过按降序对索引进行排序来工作,因此可能并不总是适合或概括任何给定的数据帧。


2
投票
这有效:

for i,r in data[::-1].iterrows(): print(r['Odd'], r['Even'])
    

2
投票
这可能比负切片更明确和可读:

df.loc[reversed(df.index)]
    
© www.soinside.com 2019 - 2024. All rights reserved.