Pandas的数据框架(Python)更接近于R的数据框架还是datatables?

9
为了理解我的问题,我首先应该指出,R datatables不仅仅是带有语法糖的R数据框,它们之间存在重要的行为差异:datatables中的列赋值/修改通过引用避免将整个对象复制到内存中(请参见此Quora答案中的示例),而在dataframes中则不然。
我已经多次发现,由于data.table的行为方式导致的速度和内存差异是至关重要的因素,这使得人们可以处理一些大型数据集,而使用data.frame的方法则不可能。
因此,我想知道的是:在Python中,Pandas的数据框在这方面的行为如何?
奖励问题:如果Pandas的数据框更接近于R数据框而不是R datatables,并且具有相同的缺点(在赋值/修改列时完全复制对象),那么是否有一个类似于R的data.table包的Python等价物?
按评论请求编辑:代码示例:
R数据框:
# renaming a column
colnames(mydataframe)[1] <- "new_column_name"

R数据表:

# renaming a column
library(data.table)
setnames(mydatatable, 'old_column_name', 'new_column_name')

在Pandas中:
mydataframe.rename(columns = {'old_column_name': 'new_column_name'}, inplace=True)

请看问题的编辑。 - François M.
1
似乎任何提供“inplace”选项的操作都可以原地执行。 - Frank
1
是的。不过,考虑到这个回答(以及问题的评论),也许并非如此:https://stackoverflow.com/a/47097979/4348534 - François M.
3
据我所理解,inplace=True通常意味着底层数据的指针会被移动,而Python对象保持其身份,但这并不会防止数据的复制。 - juanpa.arrivillaga
1
@fmalaussena 这是对 R 中发生的情况的不充分描述。虽然您将获得一个新的数据框,但未更改的列将与以前的数据框共享内存。 - hadley
显示剩余6条评论
1个回答

12

Pandas在这方面更像data.frame。您可以使用memory_profiler包进行检查;以下是在Jupyter笔记本中使用它的示例:

首先定义一个测试程序:

%%file df_memprofile.py
import numpy as np
import pandas as pd

def foo():
    x = np.random.rand(1000000, 5)
    y = pd.DataFrame(x, columns=list('abcde'))
    y.rename(columns = {'e': 'f'}, inplace=True)
    return y

然后加载内存分析器并运行 + 分析函数

%load_ext memory_profiler
from df_memprofile import foo
%mprun -f foo foo()

我获得了以下输出:

Filename: /Users/jakevdp/df_memprofile.py

Line #    Mem usage    Increment   Line Contents
================================================
     4     66.1 MiB     66.1 MiB   def foo():
     5    104.2 MiB     38.2 MiB       x = np.random.rand(1000000, 5)
     6    104.4 MiB      0.2 MiB       y = pd.DataFrame(x, columns=list('abcde'))
     7    142.6 MiB     38.2 MiB       y.rename(columns = {'e': 'f'}, inplace=True)
     8    142.6 MiB      0.0 MiB       return y

您可以看到以下几点:

  1. 在创建 y 时,它只是原始数组的轻量级包装器:即没有复制任何数据。

  2. 当重命名 y 中的列时,会在内存中复制整个数据数组(这与首次创建 x 时增加的 38MB 相同)。

因此,除非我漏掉了什么,否则 Pandas 的操作更像 R 的数据框架而不是 R 的数据表。


编辑:请注意,rename() 有一个控制此行为的参数 copy,默认为 True。例如,使用以下内容:

y.rename(columns = {'e': 'f'}, inplace=True, copy=False)

...导致原地操作而无需复制数据。

或者,您可以直接修改columns属性:

y.columns = ['a', 'b', 'c', 'd', 'f']

我认为分析器有一行出错了。我注释掉了rename()这一行,但在第7行仍然增加了38MB:"7 158.4 MiB 38.1 MiB #y.rename(columns = {'e': 'f'}, inplace=True)" - Marmaduke
@Marmaduke 我无法重现那个问题。当我注释掉那一行时,分析器会跳过它。 - jakevdp
正如您在其他地方指出的那样,它缓存了旧版本。重新启动内核可以恢复正常。 - Marmaduke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接