How to move Nan values to end in all columns

2020-04-23 02:35发布

I have a df like this,

A     B     C
a     NaN   NaN
b     NaN   NaN
c     NaN   NaN
NaN   a     NaN
NaN   b     NaN
NaN   c     NaN
NaN   NaN   a
NaN   NaN   b
NaN   NaN   c

desired_output,

A   B   C
a   a   a
b   b   b
c   c   c
NaN NaN NaN 
NaN NaN NaN 
NaN NaN NaN 
NaN NaN NaN 
NaN NaN NaN 
NaN NaN NaN

2条回答
We Are One
2楼-- · 2020-04-23 02:53

You can use a bit changed justify function:

def justify(a, invalid_val=0, axis=1, side='left'):    
    """
    Justifies a 2D array

    Parameters
    ----------
    A : ndarray
        Input array to be justified
    axis : int
        Axis along which justification is to be made
    side : str
        Direction of justification. It could be 'left', 'right', 'up', 'down'
        It should be 'left' or 'right' for axis=1 and 'up' or 'down' for axis=0.

    """

    if invalid_val is np.nan:
        #change to notnull
        mask = pd.notnull(a)
    else:
        mask = a!=invalid_val
    justified_mask = np.sort(mask,axis=axis)
    if (side=='up') | (side=='left'):
        justified_mask = np.flip(justified_mask,axis=axis)
    #change dtype to object
    out = np.full(a.shape, invalid_val, dtype=object)  
    if axis==1:
        out[justified_mask] = a[mask]
    else:
        out.T[justified_mask.T] = a.T[mask.T]
    return out

df = pd.DataFrame(justify(df.values, invalid_val=np.nan, side='up', axis=0), 
                  columns=df.columns)
print (df)
     A    B    C
0    a    a    a
1    b    b    b
2    c    c    c
3  NaN  NaN  NaN
4  NaN  NaN  NaN
5  NaN  NaN  NaN
6  NaN  NaN  NaN
7  NaN  NaN  NaN
8  NaN  NaN  NaN
查看更多
ゆ 、 Hurt°
3楼-- · 2020-04-23 03:17

You can create a boolean mask, then sort the boolean mask using argsort, and index your final array:

A = df.isnull().values

out = df.values[np.argsort(A, axis=0, kind='mergesort'), np.arange(A.shape[1])]

array([['a', 'a', 'a'],
       ['b', 'b', 'b'],
       ['c', 'c', 'c'],
       [nan, nan, nan],
       [nan, nan, nan],
       [nan, nan, nan],
       [nan, nan, nan],
       [nan, nan, nan],
       [nan, nan, nan]], dtype=object)

And to recreate the DataFrame:

pd.DataFrame(out, columns=df.columns)

     A    B    C
0    a    a    a
1    b    b    b
2    c    c    c
3  NaN  NaN  NaN
4  NaN  NaN  NaN
5  NaN  NaN  NaN
6  NaN  NaN  NaN
7  NaN  NaN  NaN
8  NaN  NaN  NaN
查看更多
登录 后发表回答