【问题标题】:Set nans across multiple pandas dataframes跨多个 pandas 数据帧设置 nans
【发布时间】:2017-01-17 17:40:48
【问题描述】:

我有许多类似的数据帧,我想在所有数据帧中标准化 nans。例如,如果 df1.loc[0,'a'] 中存在 nan,那么对于同一索引位置,所有其他数据帧都应设置为 nan。

我知道我可以将数据框分组以创建一个大型多索引数据框,但有时我发现使用一组相同结构的数据框更容易。

这是一个例子:

import pandas as pd
import numpy as np

df1 = pd.DataFrame(np.reshape(np.arange(12), (4,3)), columns=['a', 'b', 'c'])
df2 = pd.DataFrame(np.reshape(np.arange(12), (4,3)), columns=['a', 'b', 'c'])
df3 = pd.DataFrame(np.reshape(np.arange(12), (4,3)), columns=['a', 'b', 'c'])

df1.loc[3,'a'] = np.nan
df2.loc[1,'b'] = np.nan
df3.loc[0,'c'] = np.nan

print df1
print ' ' 
print df2
print ' ' 
print df3

输出:

     a   b   c
0  0.0   1   2
1  3.0   4   5
2  6.0   7   8
3  NaN  10  11

   a     b   c
0  0   1.0   2
1  3   NaN   5
2  6   7.0   8
3  9  10.0  11

   a   b     c
0  0   1   NaN
1  3   4   5.0
2  6   7   8.0
3  9  10  11.0

但是,我希望 df1、df2 和 df3 在相同的位置有 nan:

print df1
     a     b     c
0  0.0   1.0   NaN
1  3.0   NaN   5.0
2  6.0   7.0   8.0
3  NaN  10.0  11.0

使用 piRSquared 提供的答案,我能够为不同大小的数据帧扩展它。这是函数:

def set_nans_over_every_df(df_list):
    # Find unique index and column values
    complete_index = sorted(set([idx for df in df_list for idx in df.index]))
    complete_columns = sorted(set([idx for df in df_list for idx in df.columns]))

    # Ensure that every df has the same indexes and columns
    df_list = [df.reindex(index=complete_index, columns=complete_columns) for df in df_list]

    # Find the nans in each df and set nans in every other df at the same location     
    mask = np.isnan(np.stack([df.values for df in df_list])).any(0)
    df_list = [df.mask(mask) for df in df_list]

    return df_list

还有一个使用不同大小数据框的示例:

df1 = pd.DataFrame(np.reshape(np.arange(15), (5,3)), index=[0,1,2,3,4], columns=['a', 'b', 'c'])
df2 = pd.DataFrame(np.reshape(np.arange(12), (4,3)), index=[0,1,2,3], columns=['a', 'b', 'c'])
df3 = pd.DataFrame(np.reshape(np.arange(16), (4,4)), index=[0,1,2,3], columns=['a', 'b', 'c', 'd'])

df1.loc[3,'a'] = np.nan
df2.loc[1,'b'] = np.nan
df3.loc[0,'c'] = np.nan

df1, df2, df3 = set_nans_over_every_df([df1, df2, df3])

print df1

     a     b     c   d
0  0.0   1.0   NaN NaN
1  3.0   NaN   5.0 NaN
2  6.0   7.0   8.0 NaN
3  NaN  10.0  11.0 NaN
4  NaN   NaN   NaN NaN

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    我会在numpy 中设置一个mask,然后在pd.DataFrame.mask 方法中使用这个mask

    mask = np.isnan(np.stack([d.values for d in [df1, df2, df3]])).any(0)
    

    print(df1.mask(mask))
    
         a     b     c
    0  0.0   1.0   NaN
    1  3.0   NaN   5.0
    2  6.0   7.0   8.0
    3  NaN  10.0  11.0
    

    print(df2.mask(mask))
    
         a     b     c
    0  0.0   1.0   NaN
    1  3.0   NaN   5.0
    2  6.0   7.0   8.0
    3  NaN  10.0  11.0
    

    print(df3.mask(mask))
    
         a     b     c
    0  0.0   1.0   NaN
    1  3.0   NaN   5.0
    2  6.0   7.0   8.0
    3  NaN  10.0  11.0
    

    【讨论】:

      【解决方案2】:

      您可以创建掩码,然后应用到所有数据帧:

      mask = df1.notnull() & df2.notnull() & df3.notnull()
      print (mask)
             a      b      c
      0   True   True  False
      1   True  False   True
      2   True   True   True
      3  False   True   True
      

      您也可以使用reduce动态设置掩码:

      import functools
      
      masks = [df1.notnull(),df2.notnull(),df3.notnull()]
      mask = functools.reduce(lambda x,y: x & y, masks)
      print (mask)
             a      b      c
      0   True   True  False
      1   True  False   True
      2   True   True   True
      3  False   True   True
      

      print (df1[mask])
           a     b     c
      0  0.0   1.0   NaN
      1  3.0   NaN   5.0
      2  6.0   7.0   8.0
      3  NaN  10.0  11.0
      
      print (df2[mask])
           a     b     c
      0  0.0   1.0   NaN
      1  3.0   NaN   5.0
      2  6.0   7.0   8.0
      3  NaN  10.0  11.0
      
      print (df2[mask])
      
           a     b     c
      0  0.0   1.0   NaN
      1  3.0   NaN   5.0
      2  6.0   7.0   8.0
      3  NaN  10.0  11.0
      

      【讨论】:

        【解决方案3】:

        假设你所有的 DF 都具有相同的形状并具有相同的索引:

        In [196]: df2[df1.isnull()] = df3[df1.isnull()] = np.nan
        
        In [197]: df1[df3.isnull()] = df2[df3.isnull()] = np.nan
        
        In [198]: df1[df2.isnull()] = df3[df2.isnull()] = np.nan
        
        In [199]: df1
        Out[199]:
             a     b     c
        0  0.0   1.0   NaN
        1  3.0   NaN   5.0
        2  6.0   7.0   8.0
        3  NaN  10.0  11.0
        
        In [200]: df2
        Out[200]:
             a     b     c
        0  0.0   1.0   NaN
        1  3.0   NaN   5.0
        2  6.0   7.0   8.0
        3  NaN  10.0  11.0
        
        In [201]: df3
        Out[201]:
             a     b     c
        0  0.0   1.0   NaN
        1  3.0   NaN   5.0
        2  6.0   7.0   8.0
        3  NaN  10.0  11.0
        

        【讨论】:

        • 这与我尝试解决问题的方式类似,但是当您拥有大量数据帧时,它变得难以实现。
        【解决方案4】:

        一种简单的方法是将 DataFrame 相加,然后将结果乘以 0,然后将此 DataFrame 单独添加到所有其他 DataFrame。

        df_zero = (df1 + df2 + df3) * 0
        df1 + df_zero
        df2 + df_zero
        df3 + df_zero
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-05-31
          • 1970-01-01
          • 1970-01-01
          • 2020-10-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-08
          相关资源
          最近更新 更多