为啥这个字典理解这么慢?请建议加快速度的方法

Posted

技术标签:

【中文标题】为啥这个字典理解这么慢?请建议加快速度的方法【英文标题】:Why is this dictionary comprehension so slow? Please suggest way to speed it up为什么这个字典理解这么慢?请建议加快速度的方法 【发布时间】:2020-12-09 21:37:53 【问题描述】:

嗨,请帮助我:加快字典压缩速度;提供更好的方法或更好地理解为什么它在内部如此缓慢(例如,随着字典内存大小的增长,计算速度变慢)。我敢肯定,在不学习 C 的情况下一定有更快的方法!

classes = i : [1 if x in df['column'].str.split("|")[i] else 0 for x in df['column']] for i in df.index

输出: 1:[0,1,0...0],......, 4000:[0,1,1...0]

来自这样的 df:

data_ = 'drugbank_id': ['DB06605', 'DB06606', 'DB06607', 'DB06608', 'DB06609'], 
         'drug-interactions': ['DB06605|DB06695|DB01254|DB01609|DB01586|DB0212',
                               'DB06605|DB06695|DB01254|DB01609|DB01586|DB0212', 
                               'DB06606|DB06607|DB06608|DB06609', 
                               'DB06606|DB06607', 
                               'DB06608']
                             

pd.DataFrame(data = data_  , index=range(0,5) )

我在一个有 4000 行的 df 中执行它,列 df['column'] 包含一个由 | 分隔的 Id 字符串。每行中需要拆分的 ID 数量从 1 到 1000 不等,但是,这是针对所有 4000 个索引执行的。我在 df 的头上对其进行了测试,它似乎足够快,现在理解已经运行了 24 小时。所以也许这只是工作的绝对规模,但我觉得我可以加快速度,此时我想阻止它重新设计,但是,我害怕这会让我在速度没有太大提高的情况下倒退,所以在我这样做之前,我想得到一些想法、想法和建议。

超过 4000x4000 大小我怀疑使用系列和索引对象是另一个问题,我最好使用列表,但考虑到任务的大小,我不确定会获得多少速度,也许我会最好使用其他方法,例如 pd.apply(df, f(逐行写入 json))。我不确定 - 感谢任何帮助和教育,谢谢。

【问题讨论】:

看起来您在每次迭代时都在不必要地分割整个列 您能否提供一些示例数据和您的预期输出?我很肯定你可以得到一个解决方案,让这个过程只需要几秒钟,最多可能一分钟。 你为什么要“预成型”“包含一串 Ids”的“df”?为什么不直接使用set 或其他更合适的数据结构?等待 24 小时表明你做错了什么! 4k 视频的像素是所有数据的一半以上,播放视频意味着每秒处理 30 次帧。你应该能够相对容易地在 100 倍内获得 Python,即正如 @ALollz 所说,几秒钟不应该是问题 @ALollz 谢谢我添加了一些示例数据。啊,好的,谢谢哈哈,我没有意识到,但这是有道理的,所以我需要使用 df.iloc[df.index == i].str.split() 在单元格级别进行拆分。哈哈一分钟会很甜蜜 @SamMason 谢谢,我想可能是缺乏经验。我会记住你的 4K 类比。 3 小时后它还在继续,所以就让它过夜,它仍然没有完成。 id 对应于与给定 id 交互的 id,它们将是唯一的,但在 df 单元中它们当前是一个字符串。你认为我应该在 df 之外这样做吗? 【参考方案1】:

这是一种方法:

import pandas as pd

# create data frame
df = pd.DataFrame('idx': [1, 2, 3, 4], 'col': ['1|2', '1|2|3', '2|3', '1|4'])

# split on '|' to convert string to list
df['col'] = df['col'].str.split('|')

# explode to get one row for each list element
df = df.explode('col')

# create dummy ID (this will become True in the final result)
df['dummy'] = 1

# use pivot to create dense matrix
df = (df.pivot(index='idx', columns='col', values='dummy')
        .fillna(0)
        .astype(int))

# convert each row to a list
df['test'] = df.apply(lambda x: x.to_list(), axis=1)
print(df)

col  1  2  3  4          test
idx                          
1    1  1  0  0  [1, 1, 0, 0]
2    1  1  1  0  [1, 1, 1, 0]
3    0  1  1  0  [0, 1, 1, 0]
4    1  0  0  1  [1, 0, 0, 1]

【讨论】:

谢谢。我喜欢你这样做的方式,通过显示所有值的矩阵/df 让一切都变得非常清晰。我添加了 df.reset_index(inplace=True) 和 df['test'].to_dict() 以获取所需格式。很快就会在大数据集上运行,就等notebook停止了。干杯【参考方案2】:

您想要的输出可以使用dummies 来实现。我们拆分列stack,并使用max 将其转换为基于原始索引的虚拟指标。然后我们使用reindex 根据'drugbank_id' 列按您想要的顺序获取它。

最后为了得到你想要的字典,我们将转置并使用to_dict

classes = (pd.get_dummies(df['drug-interactions'].str.split('|', expand=True).stack())
             .max(level=0)
             .reindex(df['drugbank_id'], axis=1)
             .fillna(0, downcast='infer')
             .T.to_dict('list'))

print(classes)
0: [1, 0, 0, 0, 0],  #Has DB06605, No DB06606, No DB06607, No DB06608, No DB06609
 1: [1, 0, 0, 0, 0],
 2: [0, 1, 1, 1, 1],
 3: [0, 1, 1, 0, 0],
 4: [0, 0, 0, 1, 0]

【讨论】:

感谢@ALollz,在虚拟数据上工作正常,但是当我在实际 df 上尝试时,得到如下错误结尾,对此有什么想法吗? I cython_operation(self, kind, values, how, axis, min_count, **kwargs) 491 # 我们使用 iNaT 作为 ints 492 上的缺失值 # 所以预先转换以保护这个条件 --> 493 if (values == iNaT ).any(): 494 values = ensure_float64(values) 495 else: AttributeError: 'bool' object has no attribute 'any' @抱歉在完成之前保存 last traceback is: cython_operation(self, kind, values, how, axis, min_count, **kwargs) 491 # 我们使用 iNaT 作为 ints 492 上的缺失值 # 所以预先转换以保护它条件 --> 493 if (values == iNaT).any(): 494 values = ensure_float64(values) 495 else: AttributeError: 'bool' object has no attribute 'any' 对不起,我想这没有帮助 - 我应该将完整的追溯添加到我的问题吗? 不,我不会担心这一点,除非您从头到尾都有一个完整的示例,其中包含我的代码可以表明该问题。这是一个我从未遇到过的非常奇怪的问题,您使用的是哪个版本的pandas

以上是关于为啥这个字典理解这么慢?请建议加快速度的方法的主要内容,如果未能解决你的问题,请参考以下文章

下载速度的关键在哪?为啥我家下载这么慢?

为啥用 Matplotlib 绘图这么慢?

对 pandas 数据框的索引查找。为何这么慢?如何加快速度? [复制]

为啥打印到标准输出这么慢?可以提速吗?

为啥此 SIMD 代码运行速度比等效标量慢?

为啥 npm 安装速度这么慢?