pandas:优化我的代码(groupby()/ apply())

2024-03-03

我有一个形状为 (RxC) 1.5M x 128 的数据框。我执行以下操作:

  1. 我基于 6 列执行 groupby() 。这将创建约 8700 个子组,每个子组的形状为 538 x 122。
  2. 在每个子组上,我运行 apply()。此函数计算子组中每个分类值 PER 列(即 122)的频率百分比。

所以我的(伪代码:

<df = Read dataframe from file> g = df.groupby(grp_cols) g[nongrp_cols].apply(lambda d: d.apply(lambda s: s.value_counts()) / len(d.index))

该代码对我来说工作正常,所以现在我正在对其进行分析以提高性能。 apply() 函数运行大约需要 20-25 分钟。我认为问题在于它对每一列(122 次)迭代 8700 次(每个子组),这可能不是最好的方法(考虑到我的编码方式)。

谁能推荐我可以尝试加快速度的方法?

我尝试使用 python 多处理池(8 个进程)将子组分成相等的组来处理,但最终出现了一些 pickling 错误...

Thanks.


pd.DataFrame.groupby.apply 确实给了我们很大的灵活性(与 agg/filter/transform 不同,它允许您将每个子组重塑为任何形状,在您的情况下,从 538 x 122 到 N_categories x 122)。但它确实是有代价的:逐一应用灵活的函数并且缺乏矢量化。

我仍然认为解决这个问题的方法是使用多处理。您遇到的 pickle 错误很可能是因为您在 multi_processing_function 中定义了一些函数。规则是您必须将所有功能移至顶层。请参阅下面的代码。

import pandas as pd
import numpy as np

# simulate your data with int 0 - 9 for categorical values
df = pd.DataFrame(np.random.choice(np.arange(10), size=(538, 122)))
# simulate your groupby operations, not so cracy with 8700 sub-groups, just try 800 groups for illustration
sim_keys = ['ROW' + str(x) for x in np.arange(800)]
big_data = pd.concat([df] * 800, axis=0, keys=sim_keys)
big_data.shape

big_data.shape
Out[337]: (430400, 122)

# Without multiprocessing
# ===================================================
by_keys = big_data.groupby(level=0)

sample_group = list(by_keys)[0][1]
sample_group.shape

def your_func(g):
    return g.apply(lambda s: s.value_counts()) / len(g.index)

def test_no_multiprocessing(gb, apply_func):
    return gb.apply(apply_func)

%time result_no_multiprocessing = test_no_multiprocessing(by_keys, your_func)

CPU times: user 1min 26s, sys: 4.03 s, total: 1min 30s
Wall time: 1min 27

这里相当慢。让我们使用多处理模块:

# multiprocessing for pandas dataframe apply
# ===================================================
# to void pickle error, must define functions at TOP level, if we move this function 'process' into 'test_with_multiprocessing', it raises a pickle error
def process(df):
    return df.groupby(level=0).apply(your_func)

def test_with_multiprocessing(big_data, apply_func):

    import multiprocessing as mp

    p = mp.Pool(processes=8)
    # split it into 8 chunks
    split_dfs = np.array_split(big_data, 8, axis=0)
    # define the mapping function, wrapping it to take just df as input
    # apply to each chunk
    df_pool_results = p.map(process, split_dfs)

    p.close()

    # combine together
    result = pd.concat(df_pool_results, axis=0)

    return result


%time result_with_multiprocessing = test_with_multiprocessing(big_data, your_func)

CPU times: user 984 ms, sys: 3.46 s, total: 4.44 s
Wall time: 22.3 s

现在,它的速度要快得多,尤其是在 CPU 时间方面。尽管当我们拆分和重新组合结果时会产生一些开销,但在使用 8 核处理器时,预计速度会比非多处理情况快 4 - 6 倍。

最后检查两个结果是否相同。

import pandas.util.testing as pdt

pdt.assert_frame_equal(result_no_multiprocessing, result_with_multiprocessing)

漂亮地通过测试。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pandas:优化我的代码(groupby()/ apply()) 的相关文章

  • 如何获取右侧数据框中不在左侧数据框中的数据

    我有两个数据帧 我正在尝试输出其中一个数据帧中的数据 而不是另一个数据帧中的数据 我可以使用第一个数据帧中的数据 但不能使用第二个数据帧中的数据 only new old merge new outer on Employee ID Ben
  • 导入错误:无法导入名称“PandasError”

    我对在 Mac 上运行的 Python 3x 非常陌生 当前使用 python 金融的 senddex 教程 尝试运行以下脚本 import datetime as dt import matplotlib pyplot as plt fr
  • 可以memmap pandas系列。数据框怎么样?

    看来我可以通过创建 mmap d ndarray 并使用它来初始化系列来对 python 系列的底层数据进行内存映射 def assert readonly iloc try iloc 0 999 Should be non editabl
  • 创建 df 以生成给定格式的 json

    我正在尝试生成一个 df 来生成下面的 json Json数据 name flare children name K1 children name Exact size 4 name synonyms size 14 name K2 chi
  • 将非方邻接矩阵导入 Networkx python

    我在下面有一些 pandas 数据框形式的数据 其中列代表离散技能 行代表离散工作 仅当工作需要该技能时才存在 1 否则为 0 skill 1 skill 2 job 1 1 0 job 2 0 0 job 3 1 1 我想使用 netwo
  • Geopandas 数据框指向多边形

    我有一个 geopandas 数据框 由 id 和由 2D 点填充的几何列组成 我想连接每个唯一 id 的点来创建一个多边形 以便我的新数据框将多边形作为其几何形状 我的代码目前看起来像这样 polygons geopandas GeoDa
  • python pandas将文本中的数字提取到新列

    我有以下文字column A A hellothere 3 43 hellothere 3 9 我想extract仅另一个新列 B A 旁边 的数字 例如 B 3 43 3 9 I use str extract d d d expand
  • 向量化 for 循环并返回 x 天的最高价和最低价

    Overview 对于数据帧的每一行 我想计算 x 天的最高价和最低价 x 天的高点高于前 x 天 x 天的低点低于前 x 天 for 循环在此有更详细的解释post https stackoverflow com questions 70
  • 如何使用 pandas 对一系列值进行编码

    我有一个 pandas 数据框并且有一列age 我想将其编码为按特定范围分隔的分类值 例如 15岁以下的年龄应为0 15到30之间的年龄应更改为1等等 我找到了这种方法来做到这一点 在经历了关于使用的巨大困惑之后 and and age X
  • 熊猫加入具有不同索引级别/日期时间的数据帧?

    嗨 我有两个 DataFrame 如下所示 dineType menuName unique columns date y m d
  • 将具有多个时区的 pandas 列转换为单个时区

    Problem 我在 pandas DataFrame 中有一个列 其中包含带有时区的时间戳 此列中有两个不同的时区 我需要确保只有一个 这是该列末尾的输出 260003 2019 05 21 12 00 00 06 00 260004 2
  • 在 Python 中使用 mca 包

    我正在尝试使用MCA 套餐 https github com esafak mca blob master docs usage rst在Python中进行多重对应分析 我对如何使用它有点困惑 和PCA我希望fit一些数据 即找到这些数据的
  • 按最小值分组并用另一列中的值填充 NA

    我有一个如下所示的示例数据框 df pd DataFrame data uid 1 1 1 2 2 3 pagename home blah blah home blah blah startpage NA NA NA home home
  • Unpivot Pandas 数据

    我目前有一个DataFrame布置为 Jan Feb Mar Apr 2001 1 12 12 19 2002 9 2003 我想将数据 逆透视 使其看起来像 Date Value Jan 2001 1 Feb 2001 1 Mar 200
  • Python Pandas DateOffset 使用另一列中的值

    我以为这会很容易 但下面的内容并不适合我想要的 只是尝试通过使用另一列中的值将天数添加到预先存在的日期时间列来计算新的日期列 我下面的 偏移 列只有 1 位数字 df new date df orig date apply lambda x
  • 获取 pandas 中最后一次出现特定值之后的所有行

    我的数据框看起来像 ID colA 1 B 1 D 2 B 2 D 2 C 我已返回每组中事件 B 最后一次出现后的所有行 输出将是 ID colA 1 D 2 D 2 C 我试过 a df colA str contains B grou
  • 如何获取DataFrame.pct_change来计算每日价格数据的每月变化?

    我知道可以用periods争论 但是如何将分布在一个月内 例如交易日 的每日价格数据进行回报化呢 示例数据是 In 1 df AAPL 2009 01 02 16 00 00 90 36 2009 01 05 16 00 00 94 18
  • python中将对象数据类型转换为字符串问题

    如何将对象数据类型结构转换为字符串数据类型 下面的方法不起作用 该列仍然存在object转换为字符串后 astype import pandas as pd df pd DataFrame country A B C D E df dtyp
  • 根据列索引重命名 Dataframe 列

    是否有内置函数可以按索引重命名 pandas 数据框 我以为我知道列标题的名称 但事实证明第二列中有一些十六进制字符 根据我接收数据的方式 我将来可能会在第 2 列中遇到这个问题 因此我无法将这些特定的十六进制字符硬编码到 datafram
  • 数据框 - 平均列

    我在 pandas 中有以下数据框 Column 1 Column 2 Column3 Column 4 2 2 2 4 1 2 2 3 我正在创建一个数据框 其中包含第 1 列和第 2 列 第 3 列和第 4 列等的平均值 ColumnA

随机推荐

  • 在 pandas 数据框中添加缺失的时间

    我有一个pandas DataFrame在列中带有时间戳 这些值以纪元为单位 间隔 0 1 秒 价值观如1488771900 100000 1488771900 200000等等 但是 存在缺失值 所以我有1488794389 500000
  • 将文件编码为 Base64 时内存不足

    使用 Apache commons 中的 Base64 public byte encode File file throws FileNotFoundException IOException byte encoded try FileI
  • C++:C 字符串集

    我想创建一个 以便我可以使用 set find 检查某个单词是否在集合中 然而 C 字符串是指针 因此默认情况下该集合将通过指针值来比较它们 为了正确运行 必须取消引用它们并比较字符串 我可以只向构造函数传递一个指向 strcmp 函数的指
  • Python Moviepy安装问题(Windows 7x64)

    美好的一天 我在为 python 64 位和 Windows 64 位安装 moviepy 时遇到问题 库安装成功 文件ffmpeg下载 每次我运行它或使用 video VideoFileClip path OSError WinError
  • FirebaseobserveSingleEvent 保留在内存中

    我的应用程序相当多地使用 firebase 的observeSingleEventOfType 我开始意识到我的应用程序的内存随着时间的推移而增加 我已经注释掉了所有代码 除了调用以下函数的测试按钮 func loadPostsTest F
  • Windows 版 Git 中的文件名太长

    我在用着Git 1 9 0 preview20140217对于 Windows 据我所知 这个版本应该可以解决文件名太长的问题 但不适合我 我肯定做错了什么 我做错了git config core longpaths true and gi
  • OnTriggerEnter() 未调用

    我有一个玩家 球体 和 4 个敌人 胶囊 所有敌人都添加了角色控制器 它们还有一个子 GameObject 它具有一个 RigidBody 无质量 无重力 和一个附加的 Box Collider 盒子碰撞器足够大 因此您可以看到盒子内部的球
  • yocto 中的机器特定层

    我想为一台新机器 称之为 A 添加一些从上游获取的层 主要是为了使用这些层提供的机器 A 配置文件 内核和 u boot 然而 新层有几个 bbappend 文件 还有 bb 文件 其版本与我的 yocto 项目中其他机器的层不同 例如 机
  • 如何让 Org-mode 在当前窗口中打开像 [[file://file.org]] 这样的链接而不是在其他窗口中默认打开?

    我希望使用 C c C o 打开一个链接 例如 file filename org filename 在当前窗口中 而不是在其他窗口中的默认值 如何更改此组织模式默认行为 似乎是默认的 C u C c C o 是在其他窗口中强制打开链接 这
  • 从具有相同方法签名的多个接口继承的类

    假设我有三个接口 public interface I1 void XYZ public interface I2 void XYZ public interface I3 void XYZ 继承这三个接口的类 class ABC I1 I
  • 在 bookdown 文档中使用 R/exams(特别是 HTML 输出)

    我使用 bookdown 创建了一本 书 我希望能够添加交互式测验 而不需要闪亮等 是否可以使用 R exams http www R exams org http www R exams org 与预订 我主要对 HTML 输出感兴趣 P
  • 仅当索引为日期和时间时,如何根据时间选择 pandas 数据框中的行

    我有一个如下所示的数据框
  • Excel VBA如何从网络读取文本文件(未缓存)?

    我一直在使用以下代码从网络读取文本文件 import the text file into a string Function DownloadTextFile URL As String As String On Error GoTo E
  • R - 根据位置将纬度/经度点的巨大数据帧分组

    我是 R 新手 但我听说使用它确实是一个坏主意for循环 我有使用它们的工作代码 但我想改进它 因为它对于大数据来说非常慢 我已经有了一些如何改进算法的想法 但我不知道如何对其进行矢量化 或者在没有for loops 我只是将纬度 经度点分
  • .Net 属性网格。有没有办法让网格以不同的方式操作对象

    据我了解 属性网格被赋予一个对象 它可以通过使用反射提取其属性来操作该对象 我的问题是我有一组在运行时确定的参数 因此我无法静态地组成一个具有属性的类来表示这组参数 我有两个想法来解决这个问题 但这两个想法都很复杂 并且可能会消耗大量时间
  • 如果当天的闹钟时间已过,android会阻止立即触发闹钟服务

    警报管理器的参考资料说 如果指定的触发时间已经过去 则会触发警报 立即地 我在我的应用程序中面临这个问题 这是我的警报管理器代码 Intent myIntent new Intent getActivity DinnerAlarmRecei
  • Emacs:修复某些窗口的高度

    有没有办法像这样固定某个窗口的高度 汇编 缓冲区使用编译窗口高度 有window size fixed http www delorie com gnu docs elisp manual 21 elisp 441 html IDX1477
  • 沙盒解决方案似乎严重受损

    我正在学习 SharePoint 以及您可以部署的不同类型的解决方案 从我正在观看的培训来看 您似乎应该尽可能使用沙盒解决方案 这是因为农场解决方案可能会把事情搞得一团糟 但是 沙盒解决方案不支持我使用 WebPart 执行的两项主要操作
  • 在 .NET 7 中使用过滤器

    自从 NET 6 中发布以来 我一直在使用 Minimal API 为了进行验证 我一直使用手动方法 如下所示 app MapPost api user async FromService IValidator
  • pandas:优化我的代码(groupby()/ apply())

    我有一个形状为 RxC 1 5M x 128 的数据框 我执行以下操作 我基于 6 列执行 groupby 这将创建约 8700 个子组 每个子组的形状为 538 x 122 在每个子组上 我运行 apply 此函数计算子组中每个分类值 P