遍历分组行Python熊猫

时间:2020-05-14 18:19:01

标签: python pandas group-by pandas-groupby

假设我有一个这样的数据框

df_test = pd.DataFrame({"ID": [912665, 455378, 938724, 557830
                         ],
                    "NAME": ["Anna","Anna","Diana","Peter"
                            ],
                    "LAST_NAME": ["Johns","Johns","Scott","Scott"
                            ], 

                   "ADDRESS": ["Address1","Address2","Address3","Address3"],     
                   "PHONE": ['0000000001','0000000001','0000000002','0000000002' 
                        ],
                   "ngroup": [0, 0,1,1]}

                      )

df_test

result

ngroup列中有两个组-0和1

在每个组中,我都希望在NAME,LAST_NAME,ADDRESS之类的某些列之间进行比较,并提供一个名为Rate的新列,该列根据这些行是否相同为我评分。

例如

  1. 对于第0组,我们可以得到类似的费率: 5(由于名称相同)+ 30(由于姓氏相同)+ 0(由于地址不相同)+ 50(由于电话相同)= 85
  2. 对于组1: 0 + 30 + 15 + 30 = 75

迭代这些行并获得新列Rate并将其添加到当前数据帧的最佳方法是什么? 我尝试了一些不同的尝试,但暂时无法获得任何可行的解决方案。

2 个答案:

答案 0 :(得分:0)

IIUC,您可以创建带有列名的费率字典,然后分别stackmap的值,而只求和重复的值。

rates = {'NAME' : 5, 'LAST_NAME' : 30, 'ADDRESS' : 0 ,'PHONE' : 50 }

s = df.groupby('ngroup').agg(list).stack().explode().duplicated().to_frame()


s['vals'] = s.index.get_level_values(1).map(rates)


s[s[0].eq(True)].groupby(level=0).sum()

          0   vals
ngroup            
0       3.0   85.0
1       4.0  130.0

答案 1 :(得分:0)

实际上,无需在组行上重复

任务是应用一个计算每个组的费率的功能。

所需的第一个组件是lambda函数,该函数将应用于每列 在一个组(一个 Numpy 一维数组)中,检查所有元素是否相同。 实际上,它检查元素 0 是否等于所有开始的元素 从 1 并返回 1 (作为 True )或 0 作为( False

lambda v: (v[0] == v[1:]).all().astype(int)

然后这个概念是:

  • grp.values-将当前组转换为 Numpy 数组。
  • [:, 1:-1]-删除第一列( ID )和最后一列( ngroup )。
  • apply_along_axis(...)-将上述功能应用于剩余的每个 柱。参数 0 是轴编号(将函数应用于每个轴 列切片)。结果是一个由1或0组成的向量。
  • ... * [5, 30, 15, 50]-将上述向量乘以权重 列,获取列评级。
  • np.sum(...)-将它们相加,得出总体分组率。

执行此操作的代码是:

def getRate(grp):
    return np.sum(np.apply_along_axis(lambda v: (v[0] == v[1:]).all().astype(int),
        0, grp.values[:, 1:-1]) * [5, 30, 15, 50])

然后将上述功能应用于每个组:

df_test.groupby('ngroup').apply(getRate)

结果是:

ngroup
0    85
1    95
dtype: int64

请注意,组 1 的结果为0 * 5 + 1 * 30 + 1 * 15 + 1 * 50 = 95, 而不是您帖子中的 75 ,因为 PHONE 列的权重为 50 (请参见示例的第1点)。