Remove rows which have na values

Question:

I have the following datatable in python:-

#          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

From this, I want to remove all the rows which have any na values in them. How can I do this?

Thanks in advance

Asked By: Shawn Brar

||

Answers:

I never used datatable but pandas.DataFrame has isna() to select rows with na, and drop() to remove rows (or it can use del for this) and I found similar functions for datatable.


datatable can use del to remove selected rows. It can use also .isna() or == None to select rows with na. Problem is that it can filter it only on one column – so it may need for-loop to check different columns.

columns = dt.f[:]

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

print(df)

This removes values from datatable but not rows and it create empty rows like this

   |     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]

It can be better to keep rows which don’t have None

columns = dt.f[:]

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

print(df)

Result:

   |     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]

But you can use & (as operator AND) and | (as operator OR) to do the same without for-loop.

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)

But later I found that datatable has dt.rowall() and dt.rowany() to work with many columns and code can be simpler.

rowall() works like operator AND, rowany() works like operator 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)

Full working code:

I took code from my previous answer Create many lagged variables

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)
Answered By: furas

Here is one approach, assuming your frame is df (updated 2022/Aug/12, thanks to comment by @Oleksiy K)

df[dt.rowcount(f[:])==df.ncols,:]

Output:

   |     A  B          B_lag_1     B_lag_2    B_lag_3    B_lag_4  
   | int64  str32      str32       str32      str32      str32    
-- + -----  ---------  ----------  ---------  ---------  ---------
 0 |     0  −0.610938  −0.0522357  0.0470259  0.0706784  −0.342855
 1 |     1  0.996788   −0.487166   0.538717   0.550128   −2.62617 
[2 rows x 6 columns]
Answered By: langtang
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.