如何使用相似行列表中的值快速填充行中的NaN值

时间:2018-12-25 18:23:05

标签: python pandas dataframe nan

我有一个大型的数据框(约80万行)。例如,将近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

现在我在第3行和第4行中有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中的这些行是否在数据框中,例如'name' = 10'name' = 20不在其中。 / p>

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

输出为:

    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秒钟的时间。我的数据集有80万行。我要花一个月的时间去做。请帮忙!

1 个答案:

答案 0 :(得分:1)

  
      
  1. 如何快速检查相似帧_行_3和相似行_行4中的这些行是否在数据框中,例如,'name'= 10和'name'= 20。
  2.   

您可以使用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行,就像您提到的“ Dataframe中存在的第一行”一样。

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

您可以首先在特定行上切片的数据帧上使用.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上进行简单循环,找到每次迭代中要替换的最相似的行。