从熊猫数据帧构建频率字典而无需循环

时间:2019-06-24 00:09:30

标签: python python-3.x pandas dataframe bioinformatics

我需要从一个熊猫序列(从下面的数据框中的“ amino_acid”列中)制作一个频率字典,该字典还为字典中的每个条目(从“ templates”列中)添加一个相邻行。

    templates   amino_acid
0   118       CAWSVGQYSNQPQHF
1   635       CASSLRGNQPQHF
2   468       CASSHGTAYEQYF
3   239       CASSLDRLSSGEQYF
4   51        CSVEDGPRGTQYF

根据this post,我当前遍历数据帧的方法似乎效率低下,甚至是一种反模式。如何提高效率/使用最佳实践来做到这一点?

我目前的做法:

sequence_counts = {}
seqs = list(zip(df.amino_acid, df.templates))

for seq in seqs:
    if seq[0] not in sequence_counts:
        sequence_counts[seq[0]] = 0
    sequence_counts[seq[0]] += seq[1]

我已经按照以下方式看到了人们,但无法弄清楚如何对其进行调整以添加每个相应的“模板”条目:

sequence_counts = df['amino_acid'].value_counts().to_dict()

任何帮助/反馈将不胜感激! :)

2 个答案:

答案 0 :(得分:0)

只需测试@Nolan Conaway注释的代码,这是最好的做法:

df.groupby('amino_acid').templates.sum()

在此之后,您将获得一个包含所需内容的数据框,并且由于它使用了所有数据框本机函数,因此运行速度更快,并且当然更加简洁,简短和简洁。

为了提高速度,我在10 ^ 4数据帧中测量了经过时间,该代码比下面的答案快三个数量级(0.007 vs 4.3秒)。

诺兰(Nolan)应该在评论中加上一个注释,这样他才能以对熊猫数据框api的巧妙巧妙使用而受到赞誉。

我会在这里留下我的答案,以防万一有人觉得这些评论有用。

我不完全了解pandas api,但是找不到能满足您需求的api组合(但Nolan做到了!)。但是,似乎可以通过不创建列表或显式压缩数据来极大地改善代码。如果使用迭代器代替这些结构,则可以提高性能。

例如,在list(zip(df.amino_acid, df.templates))中,list并不是必需的,因为zip已经返回了一个列表。此外,您可以使用itertools库的izip函数,该函数可以提供迭代器而无需构建列表。另外,最好使用pandas迭代器构造函数而不是调用列(据我所知,它还将返回列表中的数据副本,因此在数据帧上还有另一个迭代)。

无论如何,我会尝试这样的事情。

sequence_counts = { }
for _, row in df.iterrows():
    t, aa = row['templates'], row['amino_acid']
    s = sequence_counts.get(aa, 0)
    sequence_counts[aa] = s + t

通过这种方式,您实际上只需要遍历数据一次,而数据帧会为您提供迭代器。

答案 1 :(得分:-1)

我对您的问题的理解是,您希望创建一个字典键/值,使key=amino_acidvalue is the frequency = templates

自从您成功创建带有seqs = list(zip(df.amino_acid, df.templates))的元组

您的字典可以构造为:

sequence_counts = dict(seqs)

一行:

sequence_counts = dict(zip(df.amino_acid, df.templates))

或者您可以通过这种方式做些事情:

sequence_counts = dict([(k,v) for k,v in zip(df.amino_acid,df.templates)])