【问题标题】:Python Pandas replace NaN in one column with value from another column of the same row it has be as list columnPython Pandas 将一列中的 NaN 替换为与列表列相同的行的另一列中的值
【发布时间】:2019-12-19 02:12:18
【问题描述】:

输入数据帧

data = {

'id' :[70,70,1148,557,557,104,581,69],
'r_id' : [[70,34, 44, 23, 11, 71], [70, 53, 33, 73, 41], 
          np.nan, np.nan, np.nan, np.nan,np.nan,[69, 68, 7],]
}

df = pd.DataFrame.from_dict(data)
print (df)
     id                      r_id
0    70  [70, 34, 44, 23, 11, 71]
1    70      [70, 53, 33, 73, 41]
2  1148                       NaN
3   557                       NaN
4   557                       NaN
5   104                       NaN
6   581                       NaN
7    69               [69, 68, 7]

输出数据帧,

data = {

'id' :[70,70,1148,557,557,104,581,69],
'r_id' : [[70,34, 44, 23, 11, 71], [70, 53, 33, 73, 41], 
          [1148], [557], [557], [104],[581],[69, 68, 7]]
}

df = pd.DataFrame.from_dict(data)
print (df)
     id                      r_id
0    70  [70, 34, 44, 23, 11, 71]
1    70      [70, 53, 33, 73, 41]
2  1148                    [1148]
3   557                     [557]
4   557                     [557]
5   104                     [104]
6   581                     [581]
7    69               [69, 68, 7]

我想要带有列表列的目标列 r_id 源列 id 不是列表,请参考 stackoverflow 中的以下链接, python-pandas-replace-nan-in-one-column 也尝试了以下方法,data_merge_rel.RELATED_DEVICE.fillna(data_merge_rel.DF0_Desc_Label_i.to_list(), inplace=True)

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    我们可以使用list_comprehension + Series.fillna

    首先,我们创建一个列表,其中所有id 值都转换为list 类型。 然后我们在这里用我们的列表值替换NaN

    df['temp'] = [[x] for x in df['id']]
    df['r_id'] = df['r_id'].fillna(df['temp'])
    df = df.drop(columns='temp')
    

    或者在一行中使用apply(感谢r.ook

    df['r_id'] = df['r_id'].fillna(df['id'].apply(lambda x: [x]))
    
         id                      r_id
    0    70  [70, 34, 44, 23, 11, 71]
    1    70      [70, 53, 33, 73, 41]
    2  1148                    [1148]
    3   557                     [557]
    4   557                     [557]
    5   104                     [104]
    6   581                     [581]
    7    69               [69, 68, 7]
    

    【讨论】:

    • 如果你使用列表理解,为什么不df['r_id'].fillna(df['id'].apply(lambda x: [x]))
    • 是的也在考虑。但是选择了更“可读”的方法。但将其添加为第二个选项。谢谢@r.ook
    【解决方案2】:

    您可以使用explode()groupby()

    (df.explode('r_id').ffill(axis=1).reset_index().groupby(['index','id'],sort=False).agg(list)
                                                                   .reset_index(1))
    

             id                      r_id
    index                                
    0        70  [70, 34, 44, 23, 11, 71]
    1        70      [70, 53, 33, 73, 41]
    2      1148                    [1148]
    3       557                     [557]
    4       557                     [557]
    5       104                     [104]
    6       581                     [581]
    7        69               [69, 68, 7]
    

    【讨论】:

    • 谢谢,你能把这两个解决方案都贴出来吗,我还有更大的数据框需要查看性能
    • 我以为你有两个解决方案,一个是爆炸,另一个是 group by
    • 它也在其他列上做了同样的操作:(
    • @vinsentparamanantham 你可以在agg前面使用列名,例如.groupby(['index','id'],sort=False)['r_id'].agg(list)
    【解决方案3】:

    您可以将列 id 转换为一个数组,添加一个维度,然后列出它和 fillna 与一个类似的系列:

    df['r_id'] = df['r_id'].fillna(pd.Series(df.id.to_numpy()[:,None].tolist(), index=df.index))
    print (df)
         id                      r_id
    0    70  [70, 34, 44, 23, 11, 71]
    1    70      [70, 53, 33, 73, 41]
    2  1148                    [1148]
    3   557                     [557]
    4   557                     [557]
    5   104                     [104]
    6   581                     [581]
    7    69               [69, 68, 7]
    

    或者,如果您没有很多 nan,则可能值得在执行任何操作之前仅选择这些行:

    mask_na = df.r_id.isna()
    df.loc[mask_na, 'r_id'] = pd.Series(df.loc[mask_na,'id'].to_numpy()[:,None].tolist(), 
                                        index=df[mask_na].index)
    

    【讨论】:

      【解决方案4】:

      我觉得anky_91的回答会更快,不过你也可以试试这个:

      df['r_id'] = np.where(df['r_id'].isnull(),
                            df['id'].apply(lambda x: [x]),
                            df['r_id'])
      

      输出:

           id                      r_id
      0    70  [70, 34, 44, 23, 11, 71]
      1    70      [70, 53, 33, 73, 41]
      2  1148                    [1148]
      3   557                     [557]
      4   557                     [557]
      5   104                     [104]
      6   581                     [581]
      7    69               [69, 68, 7]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-09-24
        • 2015-05-24
        • 2021-09-23
        • 1970-01-01
        • 2022-01-22
        • 2016-02-04
        • 2019-03-28
        相关资源
        最近更新 更多