如何在 Pandas 列中使用 groupby 和 cumcount 对唯一姓名进行计数?

4
我有一个长这样的数据框:
 ID ..... config_name    config_version  ...  
 aa           A                0         
 ab           A                7
 ad           A                7
 ad           A                27   
 bb           B                0     
 cc           C                0      
 cd           C                8 

我希望您对config_name进行分组,然后在每个唯一的config_version上应用cumcount,以便获得一个额外的列,如下所示:
 ID ..... config_name    config_version     config_version_count 
 aa           A                0                     0        
 ab           A                7                     1
 ad           A                7                     1  
 ad           A                27                    2 
 bb           B                0                     0
 cc           C                0                     0
 cd           C                8                     1

但是我似乎无法理解如何去做。 我尝试使用

      unique_count = df.groupby('config_name')['config_version'].cumcount()
      unique_count = pd.DataFrame({'config_name': [unique_count.index], 'config_version_count: [unique.count.values]})
      df = pd.merge(df,unique_count, on = 'config_name' , how = 'left')

以下是输出结果:
 ID ..... config_name    config_version     config_version_count 
 aa           A                0                     0        
 ab           A                7                     1
 ad           A                7                     2  
 ad           A                27                    3 
 bb           B                0                     0
 cc           C                0                     0
 cd           C                8                     1

我也尝试过。
 unique_count = df.drop_duplicates().groupby('config_name')['config_version'].cumcount()
  unique_count.reindex(df.index).ffill()
  df['config_version_count'] = unique_count

但这与第一次尝试产生了相同的输出。

您有什么想法可以解决这个问题吗?

2个回答

9

使用CategoricalIndexCategoricalIndex.codes

df['config_version_count'] = (df.groupby('config_name')['config_version']
                                .transform(lambda x: pd.CategoricalIndex(x).codes))

print (df)
   ID config_name  config_version  config_version_count
0  aa           A               0                     0
1  ab           A               7                     1
2  ad           A               7                     1
3  ad           A              27                     2
4  bb           B               0                     0
5  cc           C               0                     0
6  cd           C               8                     1

你的解决方案应该是可行的:

df['config_version_count'] = (df.drop_duplicates(['config_name','config_version'])
                                .groupby('config_name')
                                .cumcount())
df['config_version_count'] = df['config_version_count'].ffill().astype(int)

有没有办法修改这个解决方案,以考虑NaN值,使得cumcount函数在config_version值为NaN时不添加任何内容? - Pleastry
1
@Pleastry - 使用 m = df['config_name'].notna(),然后 df.loc[m, 'config_version_count'] = (df[m].groupby('config_name')['config_version'].transform(lambda x: pd.CategoricalIndex(x).codes)) - jezrael
哦,这只在“config_version”按升序排序时有效。如果config_version为[27, 0, NaN, 7, 7],则该解决方案已损坏,对于config_name =“A”。我会尝试找到解决办法,并稍后发布我的答案。 - Pleastry
1
实际上,你的解决方案的第二部分,也就是对 OP 的解决方案进行修改,在这种情况下似乎是有效的。 - Pleastry

7
使用 pd.factorize() 函数。
df['config_version_count']=df.groupby('config_name')['config_version'].\
                                  transform(lambda x: pd.factorize(x)[0])
print(df)

   ID config_name  config_version  config_version_count
0  aa           A               0                     0
1  ab           A               7                     1
2  ad           A               7                     1
3  ad           A              27                     2
4  bb           B               0                     0
5  cc           C               0                     0
6  cd           C               8                     1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接