在pandas中聚合具有相应计数的值

时间:2018-03-11 05:11:49

标签: python pandas dataframe group-by pandas-groupby

我的pandas数据框类似于:

my_df = 

chr   PI
2     5
2     5
2     5
2     6
2     6
2     8
2     8
2     8
2     8
2     8
3     5
3     5
3     5
3     5
3     9
3     9
3     9
3     9
3     9
3     9
3     9
3     7
3     7
3     4
......
......

我想将其转换为包含数据框新信息的新数据框,如:

  • chr:独特的染色体
  • unq_PI:每条染色体内唯一PI的数量
  • PI:该染色体中“PI”值的列表
  • PI_freq:各染色体中每个“PI”的长度

因此,预期输出为:

chr   unq_PI   PIs        PI_freq
2     3        5,6,8      3,2,5
3     4        5,9,7,4    4,7,2,1

我在想这样的事情:

new_df = pd.DataFrame({'chr': my_df['chr'].unique(),
         'unq_PI': my_df('chr')['unq_PI'].nunique()),
         'PIs': .......................,
         'PI_freq': ..................})

The only code that works is for `chr` when used alone; any additional code just throws an error. How can I fix this?

3 个答案:

答案 0 :(得分:3)

使用groupby + value_counts,然后使用groupby + agg

v = (df.groupby('chr')
       .PI
       .apply(pd.Series.value_counts, sort=False)
       .reset_index(level=1)
       .astype(str)
       .groupby(level=0)
       .agg(','.join)
       .rename(columns={'level_1' : 'PIs', 'PI' : 'PI_freq'})
)

这并不考虑唯一值的计数,可以使用groupby + nunique来计算:

v.insert(0, 'unq_PI', df.groupby('chr').PI.nunique())

v 

     unq_PI      PIs  PI_freq
chr                          
2         3    5,6,8    3,2,5
3         4  4,5,7,9  1,4,2,7

答案 1 :(得分:2)

您可以使用value_counts

yourdf=pd.concat([s.nunique(),s.value_counts().to_frame('n').reset_index().groupby('chr').agg(lambda x : ','.join(x.astype(str)))],1)
yourdf
Out[90]: 
    PI       PI        n
chr                     
2    3    8,5,6    5,3,2
3    4  9,5,7,4  7,4,2,1

yourdf.columns=['unq_PI','PIs','PI_freq']
yourdf
Out[93]: 
     unq_PI      PIs  PI_freq
chr                          
2         3    8,5,6    5,3,2
3         4  9,5,7,4  7,4,2,1

答案 2 :(得分:1)

如果订单很重要,请使用自定义功能:

def f(x):
    a = x.value_counts().astype(str).reindex(x.unique())
    i = ['unq_PI','PIs','PI_freq']
    return pd.Series([x.nunique(), ','.join(a.index), ','.join(a)], index=i)
df = df['PI'].astype(str).groupby(df['chr'], sort=False).apply(f).unstack().reset_index()

另一种解决方案:

df = (df.rename(columns={'PI' : 'PIs'})
        .groupby(['chr','PIs'], sort=False)
        .size()
        .rename('PI_freq')
        .reset_index(level=1)
        .astype(str)
        .groupby(level=0)
        .agg(','.join)
        .assign(unq_PI=lambda x: x['PIs'].str.count(',') + 1)
        .reset_index()
        .reindex(columns=['chr','unq_PI','PIs','PI_freq'])
       )
print (df)
   chr  unq_PI      PIs  PI_freq
0    2       3    5,6,8    3,2,5
1    3       4  5,9,7,4  4,7,2,1

<强>解释

您可以在两列中groupby获取size获取PI的唯一值及其每组的频率。然后reset_index获得第二级MultiIndex到列并转换为字符串:

df1 = (df.rename(columns={'PI' : 'PIs'})
        .groupby(['chr','PIs'], sort=False)
        .size()
        .rename('PI_freq')
        .reset_index(level=1)
        .astype(str)

       )
print (df1)
    PIs PI_freq
chr            
2     5       3
2     6       2
2     8       5
3     5       4
3     9       7
3     7       2
3     4       1

然后groupbylevel=0索引并加入join

df1 = (df.rename(columns={'PI' : 'PIs'})
        .groupby(['chr','PIs'], sort=False)
        .size()
        .rename('PI_freq')
        .reset_index(level=1)
        .astype(str)
        .groupby(level=0)
        .agg(','.join)
       )
print (df1)
         PIs  PI_freq
chr                  
2      5,6,8    3,2,5
3    5,9,7,4  4,7,2,1

最后获得count的唯一值数量,其中assign代表新列,reindex代表最终列的自定义顺序:

df1 = (df.rename(columns={'PI' : 'PIs'})
        .groupby(['chr','PIs'], sort=False)
        .size()
        .rename('PI_freq')
        .reset_index(level=1)
        .astype(str)
        .groupby(level=0)
        .agg(','.join)
        .assign(unq_PI=lambda x: x['PIs'].str.count(',') + 1)
        .reset_index()
        .reindex(columns=['chr','unq_PI','PIs','PI_freq'])
       )

print (df1)
   chr  unq_PI      PIs  PI_freq
0    2       3    5,6,8    3,2,5
1    3       4  5,9,7,4  4,7,2,1