按重复的列分组以将它们合并为一个具有相同名称的列

时间:2019-03-05 15:59:15

标签: python pandas

我正在尝试合并数据框中的重复列。我的数据框是多索引的,看起来像

                   sex_COPYL    sex_COPYR    age_COPYL    age_COPYR
ID    Date
 A    2010-01-01        NaN           F            NaN          230
 B    2010-01-01        NaN           F            NaN          487
      2010-02-01        NaN           M            NaN          488
 C    2010-01-01        NaN           M            NaN          534
 D    2012-09-08          M         NaN            432          NaN

我希望数据框看起来像

                       sex           age
ID    Date
 A    2010-01-01        F            230
 B    2010-01-01        F            487
      2010-02-01        M            488
 C    2010-01-01        M            534
 D    2012-09-08        M            432

我正在尝试通过

实现这一目标
df.groupby(df.columns.map(lambda x: x.split('_COPY')[0], 1)).apply(lambda x: x.mode(1)[0])

但是我得到了错误

ValueError: Grouper and axis must be same length

与该错误有关的其他帖子显示用户没有他们要分组的列。我的错误是由于名称重复而引起的吗?如果是,该如何解决?

3 个答案:

答案 0 :(得分:1)

替代解决方案:

# use both bfill and ffill to handle NaNs on both
# left and right of valid values
df['sex'] = (df.filter(like='sex')
               .bfill(axis=1)
               .ffill(axis=1)
               .iloc[:, 0])

df['age'] = (df.filter(like='age')
               .bfill(axis=1)
               .ffill(axis=1)
               .iloc[:, 0]
               .astype(int))

df = df[['sex', 'age']]
df
                      sex  age
ID         Date
A          2010-01-01   F  230
B          2010-01-01   F  487
           2010-02-01   M  488
C          2010-01-01   M  534
D          2012-09-08   M  432

答案 1 :(得分:1)

我们可以先转换列名称:

df.columns = [c.split('_COPY')[0] for c in df.columns]
df

Out:
    sex sex age age
ID  Date                
A   2010-01-01  NaN F   NaN 230
B   2010-01-01  NaN F   NaN 487
NaN 2010-02-01  NaN M   NaN 488
C   2010-01-01  NaN M   NaN 534
D   2012-09-08  NaN M   NaN 432

然后按列名和使用方式分组:

df.groupby(axis=1, level=0).agg(lambda x: x.mode(axis=1)[0])

Out:
        age sex
ID  Date        
A   2010-01-01  230.0   F
B   2010-01-01  487.0   F
NaN 2010-02-01  488.0   M
C   2010-01-01  534.0   M
D   2012-09-08  432.0   M

更新:原始的单行代码也可以与添加到axis=1参数列表中的groupby一起使用(因为我们是按列而不是按行分组):< / p>

df.groupby(df.columns.map(lambda x: x.split('_COPY')[0], 1), axis=1).apply(lambda x: x.mode(1)[0])

答案 2 :(得分:1)

您在分组依据中缺少axis = 1:

df.groupby(df.columns.map(lambda x: x.split('_COPY')[0], 1), axis=1).apply(lambda x: x.mode(1)[0])

替代解决方案(没有groupby,但与stack和unstack类似):

df.rename(columns=lambda x: x.split('_COPY')[0]).stack().unstack()

堆栈方法默认删除na值