如何计算列表中元素在 pandas 中的一行的出现次数

How to count the occurances of elements in list in for a row in pandas

我有一个看起来像这样的 df。它是由 group-by

产生的多索引 df
grouped = df.groupby(['chromosome', 'start_pos', 'end_pos',
                      'observed']).agg(lambda x: x.tolist())
                                          reference         zygosity    
chromosome  start_pos   end_pos observed                                            
chr1            69428   69428       G       [T, T]          [hom, hom]      
                69511   69511       G       [A, A]          [hom, hom]      
                762273  762273      A       [G, G, G]       [hom, het, hom] 
                762589  762589      C       [G]             [hom]       
                762592  762592      G       [C]             [het]       

对于每一行,我想计算合子中 het 和 hom 的数量。并创建一个名为 'count_hom' 和 'count_het'

的新列

我试过使用 for 循环,它很慢,而且在更改数据时不太可靠。有没有办法使用 df.zygosity.len().sum() 之类的方法来做到这一点,但仅适用于 het 或仅适用于 hom

使用Series.apply with List count:

grouped['count_hom'] = grouped['zygosity'].apply(lambda x: x.count('hom'))
grouped['count_het'] = grouped['zygosity'].apply(lambda x: x.count('het'))

您可以使用 explode + groupby,然后 value_counts,然后 unstack:

动态计算所有可能的值
new_df = pd.concat([df, df['zygosity'].explode().groupby(level=[0,1,2,3]).value_counts().unstack(level=4).fillna(0).add_prefix('count_').astype(int)], axis=1)

输出:

>>> new_df
                                       reference         zygosity  count_het  count_hom
chromosome start_pos end_pos observed                                                  
chr1       69428     69428   G            [T, T]       [hom, hom]          0          2
           69511     69511   G            [A, A]       [hom, hom]          0          2
           762273    762273  A         [G, G, G]  [hom, het, hom]          1          2
           762589    762589  C               [G]            [hom]          0          1
           762592    762592  G               [C]            [het]          1          0

您可以通过将 lambda 添加到 agg 来稍微调整您的 groupby 结构,而不是处理 groupby 结果,该 lambda 计算当时每个组的“het”和“hom”值你构建 grouped:

grouped = (df.groupby(['chromosome', 'start_pos', 'end_pos','observed'])
           .agg(reference=('reference', list), 
                zygosity=('zygosity', list), 
                count_het=('zygosity', lambda x: x.eq('het').sum()),
                count_hom=('zygosity', lambda x: x.eq('hom').sum())))

如果您想从所有列表中创建一个列表,您可以使用以下方法:

cols = ['chromosome', 'start_pos', 'end_pos','observed']
out = df.groupby(cols).agg(**{c: (c, list) for c in df.columns.drop('reference')}, 
                           count_het=('zygosity', lambda x: x.eq('het').sum()),
                           count_hom=('zygosity', lambda x: x.eq('hom').sum()))