如何使用自定义pandas groupby聚合函数来组合数据框中的行

时间:2016-11-20 00:16:55

标签: python pandas group-by

我的数据框包含name列和department列。 name列中的重复项具有不同的department值,但所有其他列值都相同。我希望将这些重复展平成一行,并将不同(唯一)部门值合并到一个列表中。因此,请获取每个组的第一行,然后将department值更改为该组中唯一department值的列表。因此,结果数据框应具有完全相同的列,但name列中没有重复,department列现在包含至少一个元素的列表。

我想使用groupby并将自定义聚合函数传递给agg(),但以下内容完全失败。我的想法是我的聚合函数会将每个组作为数据帧,如果每个数据帧组都返回一个系列,那么groupby.agg(flatten_departments)的输出将是一个数据帧。

def flatten_departments(name_group):
    #I thought name_group would be a df of that group 

    #this group is length 1 so this name doesn't actually repeat so just return same row
    if len(name_group) == 1:
        return name_group.squeeze() #turn length-1 df into a series to return, don't worry that department is a string and not a list for now
    else:
        #treat name_group like a df and get the unique departments
        departments = list(name_group['department'].unique())
        name_ser = name_group.iloc[0,:] #take first "row" of this group
        name_ser['department'] = departments #replace department value with list of unique values from group

        return name_ser

my_df = my_df.groupby(['name']).agg(flatten_departments)

这是一场灾难,name_group不是df,而是一个系列,其索引是原始df的索引,name是原始df中其他列的名称,并为该列的值赋值。

我知道我可以在groupby对象上执行for循环,如下所示

list_of_ser = []
for name, gp in my_df.groupby(['name']):
    if len(gp) == 1:
        list_of_ser.append(gp.squeeze())
    else:
        new_ser = gp.iloc[0,:]
        new_ser['department'] = list(gp['department'].unique())
        list_of_ser.append(new_ser)

new_df = pd.DataFrame(list_of_ser, columns=my_df.columns)

但我只是认为这是agg

的重点

任何想法如何使用agg完成我的目标,或者for循环是否真的是正确的方法。如果for循环是正确的,那么agg是什么意思?

谢谢!

1 个答案:

答案 0 :(得分:1)

const query = (sql, values) => {
  return new Promise((resolve, reject) => {
    // maybe use a connection Pool and log the statement for debugging
    connection.query(sql, values, (err, rows) => {
      if (err)
        return reject(err)
      resolve(rows)
    })
  })
}

enter image description here

df = pd.DataFrame( dict( name=list('ABCDEFGACEF'), dept=list('xyxyzxyzyxz') ) ) df.groupby('name').dept.apply(list).reset_index() 可以像这样使用

agg

如果您需要保留所有其他列

df.groupby('name').dept.agg(dict(dept=lambda x: list(x))).reset_index()