是否pandas.DataFrame.groupby创建数据副本或仅创建视图?在(不大可能)不创建副本的情况下,额外的内存开销是多少?它如何与原始数据帧特性(例如行数,列数,不同的组数)一起缩放?
自从有人要求我帮助他们解决这个问题以来,我对此做了更多的研究,并且自从编写了接受的答案以来,pandas 源代码已经进行了一些修改。
\n根据我从源代码中可以看出:
\nGroupby 返回 Grouper 对象上的组(即 Grouper.groups),它们是groupby 指令 \xe2\x80\x9ca 规范\xe2\x80\x9d。
\n好吧,那这是什么意思呢?
\n\xe2\x80\x9cGroupers 最终是索引映射。\xe2\x80\x9d
\n我一直认为这意味着 groupby 正在创建一个新对象。它不是原始数据帧的完整副本,因为您正在执行选择和聚合。所以从这个意义上来说,它更像是一种转变。
\n如果你对视图的定义是这样的 “视图只不过是存储在数据库中的具有关联名称的 SQL 语句。视图实际上是预定义 SQL 查询形式的表的组合”,那么我想知道您真正要问的是每次在同一个数据帧上执行相同的分组时是否必须重新应用 groupby 操作?
\n如果这就是你问的,我会说答案是否定的,它不像视图,只要存储分组操作的结果即可。分组数据帧或系列的输出对象是(新)数据帧或系列。
\nPandas 中的groupby 代码有点复杂,所以很难从第一原则中找出来。快速测试使内存使用量似乎随着数据的增长而增长,并且更多的组 = 更多的内存,但它似乎没有制作完整副本或任何东西:
In [7]: df = pd.DataFrame(np.random.random((1000,5)))
In [8]: def ret_df(df):
...: return df
In [9]: def ret_gb_df(df):
...: return df, df.groupby(0).mean()
In [10]: %memit ret_df(df)
peak memory: 75.91 MiB, increment: 0.00 MiB
In [11]: %memit ret_gb_df(df)
peak memory: 75.96 MiB, increment: 0.05 MiB
In [12]: df = pd.DataFrame(np.random.random((100000,5)))
In [13]: %memit ret_df(df)
peak memory: 79.76 MiB, increment: -0.02 MiB
In [14]: %memit ret_gb_df(df)
peak memory: 94.88 MiB, increment: 15.12 MiB
In [15]: df = pd.DataFrame(np.random.random((1000000,5)))
In [16]: %memit ret_df(df)
peak memory: 113.98 MiB, increment: 0.01 MiB
In [17]: %memit ret_gb_df(df)
peak memory: 263.14 MiB, increment: 149.16 MiB
In [18]: df = pd.DataFrame(np.random.choice([0,1,2,3], (1000000, 5)))
In [19]: %memit ret_df(df)
peak memory: 95.34 MiB, increment: 0.00 MiB
In [20]: %memit ret_gb_df(df)
peak memory: 166.91 MiB, increment: 71.56 MiB
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
817 次 |
| 最近记录: |