2016-11-20 39 views
2

我有一个数据帧,其中有一个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的索引,并将其命名是在原DF和值值一些列该列的名称。

我知道我可以只是做一个for循环在groupby对象如下

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
df = pd.DataFrame(
    dict(
     name=list('ABCDEFGACEF'), 
     dept=list('xyxyzxyzyxz') 
    ) 
) 

df.groupby('name').dept.apply(list).reset_index() 

enter image description here


agg可能已被使用这样

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

,如果你需要保留所有其他列

df = pd.DataFrame(
    dict(
     name=list('ABCDEFGACEF'), 
     dept=list('xyxyzxyzyxz') 
    ) 
) 

g = df.groupby('name') 
pd.concat([g.dept.apply(list), g.first().drop('dept', 1)], axis=1).reset_index() 
+0

感谢您的回答,单行申请完全是老板。我也理解你的'agg'例子,使用字典符号表示,如在“”中所做的那样。我想我仍然感到困惑的是,如何在参数是函数的地方使用'agg' - 在'agg'中该函数的“规则”是什么?为什么它通过一系列其他随机列?! – ministry

+0

请参阅'.agg'之前的'.dept'。这意味着我已经将'agg'限制在一个系列中。这意味着'dict(dept = lambda)'指定它将使用'lambda'并调用'dept'列。改变'dict'中的'dept',你将有不同的列名。在这种情况下我不会使用'agg'。我只是想给你一个例子,以便你能更好地了解发生了什么。 – piRSquared

+0

来自'apply'调用的数据框只有'name'和'department'列 - 我怎样才能得到剩下的列呢? – ministry