删除具有 na 值的行

Remove rows which have na values

我在 python 中有以下 datatable:-

#          A        B               B_lag_1         B_lag_2         B_lag_3         B_lag_4
#0         0        −0.342855       NA              NA              NA              NA
#1         0        0.0706784       −0.342855       NA              NA              NA
#2         0        0.0470259       0.0706784       −0.342855       NA              NA
#3         0        −0.0522357      0.0470259       0.0706784       −0.342855       NA
#4         0        −0.610938       −0.0522357      0.0470259       0.0706784       −0.342855
#5         1        −2.62617        NA              NA              NA              NA
#6         1        0.550128        −2.62617        NA              NA              NA
#7         1        0.538717        0.550128        −2.62617        NA              NA
#8         1        −0.487166       0.538717        0.550128        −2.62617        NA
#9         1        0.996788        −0.487166       0.538717        0.550128        −2.62617

据此,我想删除所有包含任何 na 值的行。我该怎么做?

提前致谢

我从未使用过 datatable,但 pandas.DataFrameisna() 到 select 行,其中 nadrop() 删除行(或它可以为此使用 del),我发现 datatable.

有类似的功能

datatable 可以使用 del 删除 selected 行。它也可以使用 .isna()== None 到 select 行 na。问题是它只能在一列上过滤它 - 所以它可能需要 for-loop 来检查不同的列。

columns = dt.f[:]

for n in range(1, 5):
    rows = (dt.f[f'B_lag_{n}'] == None)
    del df[rows, columns]

print(df)

这会从数据表中删除值而不是行,并且会像这样创建空行

   |     A          B    B_lag_1    B_lag_2    B_lag_3    B_lag_4
   | int64    float64    float64    float64    float64    float64
-- + -----  ---------  ---------  ---------  ---------  ---------
 0 |    NA  NA         NA         NA         NA         NA       
 1 |    NA  NA         NA         NA         NA         NA       
 2 |    NA  NA         NA         NA         NA         NA       
 3 |    NA  NA         NA         NA         NA         NA       
 4 |     0  -0.234153   1.52303    0.647689  -0.138264   0.496714
 5 |    NA  NA         NA         NA         NA         NA       
 6 |    NA  NA         NA         NA         NA         NA       
 7 |    NA  NA         NA         NA         NA         NA       
 8 |    NA  NA         NA         NA         NA         NA       
 9 |     1   0.54256   -0.469474   0.767435   1.57921   -0.234137
[10 rows x 6 columns]

最好保留没有 None

的行
columns = dt.f[:]

for n in range(1, 5):
    rows = (dt.f[f'B_lag_{n}'] != None)
    df = df[rows, columns]

print(df)

结果:

   |     A          B    B_lag_1   B_lag_2    B_lag_3    B_lag_4
   | int64    float64    float64   float64    float64    float64
-- + -----  ---------  ---------  --------  ---------  ---------
 0 |     0  -0.234153   1.52303   0.647689  -0.138264   0.496714
 1 |     1   0.54256   -0.469474  0.767435   1.57921   -0.234137
[2 rows x 6 columns]

但是您可以使用 &(作为运算符 AND)和 |(作为运算符 OR)在没有 for 循环的情况下执行相同的操作.

columns = dt.f[:]

rows = (dt.f['B_lag_1'] != None) & (dt.f['B_lag_2'] != None) & (dt.f['B_lag_3'] != None) & (dt.f['B_lag_4'] != None)

df = df[rows, columns]

print(df)

但后来我发现datatabledt.rowall()dt.rowany()可以处理很多列并且代码可以更简单。

rowall() 类似于运算符 ANDrowany() 类似于运算符 OR.

columns = dt.f[:]

rows = dt.rowall(dt.f['B_lag_1', 'B_lag_2', 'B_lag_3', 'B_lag_4'] != None)
#rows = dt.rowall(dt.f['B_lag_1':'B_lag_4'] != None)  # range of columns
#rows = dt.rowall(dt.f[:] != None)                    # all columns

df = df[rows, columns]

print(df)

完整的工作代码:

我从我之前的回答中提取了代码

import datatable as dt
import numpy as np

def test1(df):
    print('\n--- test 1 ---\n')
    
    df = df.copy()

    #columns = dt.f['A', 'B', 'B_lag_1', 'B_lag_2', 'B_lag_3', 'B_lag_4']
    #columns = df.keys()
    columns = dt.f[:]
    
    for n in range(1, 5):
        rows = (dt.f[f'B_lag_{n}'] == None)
        del df[rows, columns]

    print(df)    
        
def test2(df):
    print('\n--- test 2 ---\n')
    
    df = df.copy()

    #columns = dt.f['A', 'B', 'B_lag_1', 'B_lag_2', 'B_lag_3', 'B_lag_4']
    #columns = df.keys()
    columns = dt.f[:]

    for n in range(1, 5):
        rows = (dt.f[f'B_lag_{n}'] != None)
        df = df[rows, columns]
    
    print(df)

def test3(df):
    print('\n--- test 3 ---\n')
    
    df = df.copy()
    
    rows = (dt.f['B_lag_1'] != None) & (dt.f['B_lag_2'] != None) & (dt.f['B_lag_3'] != None) & (dt.f['B_lag_4'] != None)

    columns = dt.f[:]
    
    df = df[rows, columns]
    
    print(df)

def test4(df):
    print('\n--- test 4 ---\n')
    
    df = df.copy()

    columns = dt.f[:]
    
    #rows = dt.rowall(dt.f['B_lag_1', 'B_lag_2', 'B_lag_3', 'B_lag_4'] != None) # use columns in some range
    #rows = dt.rowall(dt.f['B_lag_1':'B_lag_4'] != None) # use columns in some range
    #rows = dt.rowall(dt.f[float] != None)               # use columns which have float values
    rows = dt.rowall(dt.f[:] != None)                    # use all columns

    df = df[rows, columns]
    
    print(df)
    
    
# --- main ---

np.random.seed(42)

df = dt.Frame({
    "A": np.repeat(np.arange(0, 2), 5), 
    "B": np.random.normal(0, 1, 10)
})

for n in range(1, 5):
    df[f'B_lag_{n}'] = df[:, dt.shift(dt.f.B, n), dt.by('A')]['B']

# --- tests ---

test1(df)
test2(df)
test3(df)
test4(df)