【问题标题】:How to combine numeric columns in pandas dataframe with NaN?如何将 pandas 数据框中的数字列与 NaN 结合起来?
【发布时间】:2020-07-29 04:06:42
【问题描述】:

我有一个这种格式的数据框:

ID measurement_1 measurement_2
0      3              NaN
1      NaN            5
2      NaN            7 
3      NaN            NaN

我想合并到:

ID measurement measurement_type
0      3              1
1      5              2
2      7              2

对于每一行,measurement_1measurement_2 列中都会有一个值,而不是两者都有,另一列将为 NaN。 在某些行中,两列都是 NaN。

我想为测量类型添加一列(取决于哪一列具有值)并从两列中取出实际值,并删除两列中都包含 NaN 的行。

有没有简单的方法可以做到这一点?

谢谢!

【问题讨论】:

  • 你能发布一个示例输出吗?
  • 示例输出是显示的第二个数据帧

标签: python pandas dataframe


【解决方案1】:

使用DataFrame.stack 重塑数据框,然后使用reset_index 并使用DataFrame.assign 通过在Series.str.split 上使用Series.str.split + Series.str[:1] 来分配列measurement_type

df1 = (
    df.set_index('ID').stack().reset_index(name='measurement')
    .assign(mesurement_type=lambda x: x.pop('level_1').str.split('_').str[-1])
)

结果:

print(df1)
   ID  measurement mesurement_type
0   0          3.0               1
1   1          5.0               2
2   2          7.0               2

【讨论】:

    【解决方案2】:

    也许combine_first 能帮上忙?

    import numpy as np
    
    
    df["measurement"] = df["measurement_1"].combine_first(df["measurement_2"])
    df["measurement_type"] = np.where(df["measurement_1"].notnull(), 1, 2)
    df.drop(["measurement_1", "measurement_2"], 1)
    

        ID  measurement measurement_type
    0   0   3           1
    1   1   5           2
    2   2   7           2
    
    

    【讨论】:

      【解决方案3】:

      设置一个阈值并丢弃任何具有多个NaN 的内容。使用df.assignfillna()measurement_1 并在measurement_2 上应用np.where

        df= df.dropna(thresh=2).assign(measurement=df.measurement_1.fillna\
                                   (df.measurement_2), measurement_type=np.where(df.measurement_2.isna(),1,2)).drop(columns=['measurement_1','measurement_2'])
      
          ID  measurement  measurement_type
      0   0              3              1
      1   1              5              2
      2   2              7              2
      

      【讨论】:

        【解决方案4】:

        你可以使用pandas melt

        (
            df.melt("ID", var_name="measurement_type", value_name="measurement")
            .dropna()
            .assign(measurement_type=lambda x: x.measurement_type.str[-1])
            .iloc[:, [0, -1, 1]]
            .astype("int8")
        )
        

        wide to long

        (
            pd.wide_to_long(df, stubnames="measurement", i="ID", 
                            j="measurement_type", sep="_")
            .dropna()
            .reset_index()
            .astype("int8")
            .iloc[:, [0, -1, 1]]
        )
        
        
        
            ID  measurement measurement_type
        0   0          3        1
        1   1          5        2
        2   2          7        2
        

        【讨论】:

          猜你喜欢
          • 2021-11-13
          • 2021-07-25
          • 2021-09-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-10-25
          • 2023-01-30
          • 1970-01-01
          相关资源
          最近更新 更多