【问题标题】:How to quickly fill NaN values in a row with the ones in a list of similar rows如何用相似行列表中的值快速填充一行中的 NaN 值
【发布时间】:2018-12-26 03:01:45
【问题描述】:

我有一个大数据框(大约 800,000 行)。例如,将近 30% 的行具有 NaN 值,

test = pd.DataFrame({"name": [1,2,3,4,5,6,7], 
                     "col1": ['c1', 'c2', 'c3', 'c4', 'c5', 'c6', 'c7'], 
                     "col2": [4, 5, 6, np.nan, np.nan, 8, 5], 
                     "col3": [7, 8, 9, np.nan, np.nan, 3, 7], 
                     "col4": [7, 8, 9, np.nan, np.nan, 2, 6]})

    name  col1  col2   col3  col4    
0    1     c1    4.0    7.0   7.0
1    2     c2    5.0    8.0   8.0    
2    3     c3    6.0    9.0   9.0    
3    4     c4    NaN    NaN   NaN    
4    5     c5    NaN    NaN   NaN    
5    6     c6    8.0    3.0   2.0    
6    7     c7    5.0    7.0   6.0

现在我在 row3 和 row4 中有 NaN。

根据一些规则,我得到的 row3 最相似的行是

similar_for_row3 = ['name' = 10, 'name' = 3, 'name' = 1]

对于第 4 行是

similar_for_row4 = ['name' = 2, 'name' = 6, 'name' = 20].

那么,我的问题是:

  1. 如何快速检查similar_for_row3similar_for_row4 中的这些行是否在Dataframe 中,例如'name' = 10'name' = 20 不在其中。

  2. 用相似行中的值快速替换一行中的NaN 值。例如row3,我们首先检查similar_for_row3中的所有行,然后使用Dataframe中存在的第一行(即test.loc[test['name' == 3]])替换row3中的NaN

输出是:

    name  col1  col2   col3  col4    
0    1     c1    4.0    7.0   7.0    
1    2     c2    5.0    8.0   8.0    
2    3     c3    6.0    9.0   9.0    
3    4     c4    6.0    9.0   9.0  -> replace NaN with 'name' = 3    
4    5     c5    NaN    NaN   NaN    
5    6     c6    8.0    3.0   2.0    
6    7     c7    5.0    7.0   6.0

我尝试使用“for 循环”迭代所有 Dataframe 以替换 NaN 值,但速度很慢。更换一排大约需要 3 秒。我的数据集有 800,000 行。我要花一个月的时间来做这件事。请帮忙!

【问题讨论】:

    标签: python pandas dataframe nan


    【解决方案1】:
    1. 如何快速检查similar_for_row3 和similar_for_row4 中的这些行是否在Dataframe 中,例如'name' = 10 和'name' = 20 不在其中。

    您可以使用& 找到两个sets 的交集,并使用sorted 设置key= similar_for_row3.index 以便使用similar_for_row3 中出现的第一个交集:

    similar_for_row4 = [2, 6, 20]
    fill_with  = sorted(list(set(similar_for_row4) & set(test.name.values)), 
           key= similar_for_row4.index)[0]
    #2
    

    所以这里第 2 行将用于替换第 4 行,正如您提到的“数据帧中存在的第一行”。

    1. 用相似行中的值快速替换一行中的 NaN 值。例如,对于row3,我们首先检查similar_for_row3中的所有行,然后使用Dataframe中存在的第一行(即test.loc[test['name' == 3]])替换row3中的NaN。

    您可以首先使用.isnull() 对在特定行上切片的数据帧创建一个掩码,然后对数据帧执行布尔索引以过滤对应的列,在本例中为第 2 行:

    row = 4
    mask = test.loc[row, :].isnull().squeeze()
    test.loc[row, mask] = test.loc[fill_with, mask].values
    

    所以对于这个例子,你会:

        name col1 col2  col3  col4
    0     1   c1   4.0   7.0   7.0
    1     2   c2   5.0   8.0   8.0
    2     3   c3   6.0   9.0   9.0
    3     4   c4   NaN   NaN   NaN
    4     5   c5   6.0   9.0   9.0
    5     6   c6   8.0   3.0   2.0
    6     7   c7   5.0   7.0   6.0
    

    更新

    为了轻松检测存在任何 NaN 的行,您可以执行以下操作:

    has_nans = test[test.isnull().any(axis=1)].index.values
    

    然后在has_nans 上进行简单循环,找到每次迭代中要替换的最相似的行。

    【讨论】:

    • 嗨尼克松,您的解决方案非常有帮助。我还有一个问题 - 我是否必须循环所有具有 NaN 值的行并重复您提供的解决方案,还是您知道更好的方法?
    • 很高兴它有帮助。更新了一些关于此的提示。如果有帮助请不要忘记接受
    猜你喜欢
    • 2021-11-08
    • 1970-01-01
    • 2017-04-28
    • 2018-04-15
    • 2019-09-26
    • 2020-09-14
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    相关资源
    最近更新 更多