【问题标题】:Melt pandas dataframe based on condition根据条件融化熊猫数据框
【发布时间】:2021-12-28 09:45:57
【问题描述】:

我有一个格式如下的数据框

timestamp ID Col1 Col2 Col3 Col4 UsefulCol
16/11/2021 1 0.2 0.1 Col3
17/11/2021 1 0.3 0.8 Col3
17/11/2021 2 10 Col2
17/11/2021 3 0.1 2 Col4

我想把它“融化”成这种格式:

timestamp ID Col Value
16/11/2021 1 Col3 0.1
17/11/2021 1 Col3 0.8
17/11/2021 2 Col2 10
17/11/2021 3 Col4 2

我该怎么办?

作为数据框输入:

from numpy import nan
df = pd.DataFrame({'timestamp': ['16/11/2021', '17/11/2021', '17/11/2021', '17/11/2021'],
                   'ID': [1, 1, 2, 3],
                   'Col1': [0.2, 0.3, nan, nan],
                   'Col2': [nan, nan, 10.0, nan],
                   'Col3': [0.1, 0.8, nan, 0.1],
                   'Col4': [nan, nan, nan, 2.0],
                   'UsefulCol': ['Col3', 'Col3', 'Col2', 'Col4']})

【问题讨论】:

    标签: python pandas dataframe melt


    【解决方案1】:

    尝试先创建一个包含有用值的列:

    df['Value'] = df.apply(lambda x: x[x.UsefulCol], axis=1)

    timestamp   ID    Col1    Col2    Col3    Col4    UsefulCol    Value
    16/11/2021  1     0.2             0.1             Col3         0.1
    17/11/2021  1     0.3             0.8             Col3         0.8
    17/11/2021  2              10                     Col2         10
    17/11/2021  3                     0.1     2       Col4         2
    

    然后,您可以删除要融化的列:

    df.drop(['Col1', 'Col2', 'Col3', 'Col4], axis=1, inplace=True)

    timestamp   ID    UsefulCol    Value
    16/11/2021  1     Col3         0.1
    17/11/2021  1     Col3         0.8
    17/11/2021  2     Col2         10
    17/11/2021  3     Col4         2
    

    根据需要重命名列:

    df.rename({'UsefulCol':'Col'}, axis=1, inplace=True)

    df.columns = [timestamp', 'ID', 'Col', 'Value]

    【讨论】:

      【解决方案2】:

      这是一个使用一点 numpy 的矢量解决方案:

      import numpy as np
      
      # select columns to pseudo-melt (this could be a manual list cols=['A', 'B', 'C'])
      cols = df.filter(regex='^Col').columns
      
      # slice the needed values (they will be on the diagonal) and keep only diagonal
      df['Value'] = np.diag(df.filter(regex='^Col').loc[:, df['UsefulCol']].values)
      
      # drop old columns
      new_df = df.drop(columns=cols)
      

      输出:

          timestamp  ID UsefulCol     Value
      0  16/11/2021   1      Col3    0.1000
      1  17/11/2021   1      Col3    0.8000
      2  17/11/2021   2      Col2   10.0000
      3  17/11/2021   3      Col4    2.0000
      

      【讨论】:

      • 谢谢。我喜欢这个想法,但不幸的是它不适用于我的情况。我收到错误消息:“无法为形状为 (129710, 129710) 且数据类型为 float64 的数组分配 125.GiB”。在我的情况下,创建一个巨大的方阵来取对角线是无效的。再次感谢
      • @MLlearner 是的,这不适用于非常大的数据集(不确定这是否是投反对票的原因)
      猜你喜欢
      • 1970-01-01
      • 2021-10-27
      • 2018-06-21
      相关资源
      最近更新 更多