【问题标题】:How to combine multiple rows of same category to one in pandas?如何在熊猫中将多行相同类别的行合并为一个?
【发布时间】:2017-12-19 12:30:00
【问题描述】:

我正在尝试从图像中的表 1 到表 2,但我似乎无法正确处理。我尝试使用数据透视表将 col A - D 从行更改为 cols。然后我尝试 groupby 但它没有给我一行而是弄乱了我的数据框。

【问题讨论】:

  • df = df.groupby(level=0, axis=1).max()
  • 另外,请将您的图片转换为可重现的数据示例,以便为您提供可验证的答案。
  • 它不工作。我还有 4 行而不是 1 行
  • 请阅读我的第二条评论。

标签: python pandas dataframe merge


【解决方案1】:

您可以使用列中的值填充空值并删除重复项:

与:

df = pd.DataFrame([["A", pd.np.nan, pd.np.nan, "Y", "Z"],
              [pd.np.nan, "B", pd.np.nan, "Y", "Z"],
              [pd.np.nan,pd.np.nan, "C", "Y", "Z"]], columns=list("ABCDE"))
df
     A    B    C  D  E
0    A  NaN  NaN  Y  Z
1  NaN    B  NaN  Y  Z
2  NaN  NaN    C  Y  Z

df.ffill().bfill().drop_duplicates()
   A  B  C  D  E
0  A  B  C  Y  Z

df.ffill().bfill() 给出:

   A  B  C  D  E
0  A  B  C  Y  Z
1  A  B  C  Y  Z
2  A  B  C  Y  Z

根据您的评论,您可以定义一个函数,用同一列中其他位置的唯一值填充第一行的缺失值。

def fillna_uniq(df, col):
    if isinstance(col, list):
        for c in col:
            df.loc[df.index[0], c] = df[c].dropna().iloc[0]
    else:
        df.loc[df.index[0], col] = df[col].dropna().iloc[0]
    return df.iloc[[0]]

你可以这样做:

fillna_uniq(df.copy(), ["B", "C", "D"])
       A  B   C     D       E     F
0  Hello  I  am  lost  Pandas  Data

我认为它有点快。您可以通过直接传递数据框而不是副本来修改 df 就地。

HTH

【讨论】:

  • 但是有没有办法优化这个?我需要大约 15 秒来完成这个填充。
  • @user8706644 你可以只填充第一行,而不是删除重复,只保留第一行。如果你有一个巨大的df可能会更好。
  • 我实际上是在 df.groupby(['E,F']).ffill().bfill().drop_duplicates() 上运行的自定义方法是否适用于组?
  • 当然,groupby 对象只是许多较小的 df,您可以在其上应用某些东西。我稍微修改了函数,有了这个,它就可以工作了:df.groupby(["E", "F"]).apply(lambda x: fillna_uniq(x.copy(), ["A", "B", "C", "D"])).reset_index(drop=True)
【解决方案2】:

一种方法是使用applydropna

假设上表中的那些空白确实是空值:

df = pd.DataFrame({'A':['Hello',np.nan,np.nan,np.nan],'B':[np.nan,'I',np.nan,np.nan],
                   'C':[np.nan,np.nan,'am',np.nan],
                  'D':[np.nan,np.nan,np.nan,'lost'],
                  'E':['Pandas']*4,
                  'F':['Data']*4})

print(df)
       A    B    C     D       E     F
0  Hello  NaN  NaN   NaN  Pandas  Data
1    NaN    I  NaN   NaN  Pandas  Data
2    NaN  NaN   am   NaN  Pandas  Data
3    NaN  NaN  NaN  lost  Pandas  Data

使用apply,您可以将 lambda 函数应用于数据帧的每一列,首先删除空值,然后找到最大值:

df.apply(lambda x: x.dropna().max()).to_frame().T

       A  B   C     D       E     F
0  Hello  I  am  lost  Pandas  Data

或者如果你的空格真的是空字符串,那么你可以这样做:

df1 = df.replace(np.nan,'')
df1
       A  B   C     D       E     F
0  Hello               Pandas  Data
1         I            Pandas  Data
2            am        Pandas  Data
3                lost  Pandas  Data

df1.apply(lambda x: x[x!=''].max()).to_frame().T

       A  B   C     D       E     F
0  Hello  I  am  lost  Pandas  Data

【讨论】:

    猜你喜欢
    • 2022-08-18
    • 2022-12-06
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 2017-01-31
    • 1970-01-01
    • 2020-10-26
    • 1970-01-01
    相关资源
    最近更新 更多