从下一列中删除NaN值并移动值

时间:2020-06-29 17:22:00

标签: python pandas list dataframe nan

我正在尝试从数据帧中删除NaN值(而不删除整个列或行),并将下一个值移到上一列。 示例:

        CLIENT| ANIMAL_1 | ANIMAL_2 | ANIMAL_3| ANIMAL_4
ROW_1     1   |   cow    | frog     | NaN     | dog
ROW_2     2   |   pig    | NaN      | cat     | NaN

我的目标是:

       CLIENT| ANIMAL_1 | ANIMAL_2 | ANIMAL_3| ANIMAL_4
ROW_1     1   |   cow    | frog     | dog     | NaN
ROW_2     2   |   pig    | cat      | NaN     | NaN

我尝试过的事情:

  1. 将每一行转换为列表,并从每一行中删除NaN。但我似乎无法从列表中删除值:

    x = df[df.CLIENT == 1].iloc[:,1:].values.tolist()

然后我得到:

[['cow', 'frog', nan, 'dog']]

删除我尝试过的“ nan”:

row_without_nan = [animal for animal in x if str(animal) != 'nan']

但是它不会更改列表中的任何内容。我尝试将空值更改为另一个单词并使用该单词,但是它也不起作用。

  1. 将每一行转换为数组。我尝试使用np.array()转换为数组,但是它没有用,因为空值变为'nan',当我尝试使用np.isnan时,我得到了:TypeError: ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

有人知道我的清单在做什么错吗,或者有更聪明/更快的方法吗?

3 个答案:

答案 0 :(得分:3)

这是一种方法:

df_out = df.apply(lambda x: pd.Series(x.dropna().to_numpy()), axis=1)
df_out = df_out.set_axis(df.columns[:df_out.shape[1]], axis=1).reindex(df.columns, axis=1)
df_out

输出:

       CLIENT ANIMAL_1 ANIMAL_2 ANIMAL_3  ANIMAL_4
ROW_1       1      cow     frog      dog       NaN
ROW_2       2      pig      cat      NaN       NaN

详细信息,在每一行上使用dropna,但是您需要转换为numpy数组以删除索引,然后将列标题分配给原始数据帧,并沿列重新索引以在数据帧末尾拾取所有空列。

答案 1 :(得分:2)

这是另一种方式:

def drop_nan(r):
    r = list(r)
    r = [x for x in r if isinstance(x, str) or not np.isnan(x)]
    return r

res = pd.DataFrame.from_records(df.apply(drop_nan, axis=1))
res.columns = df.columns[:len(res.columns)]

结果是:

   CLIENT ANIMAL_1 ANIMAL_2 ANIMAL_3
0       1      cow     frog      dog
1       2      pig      cat     None

答案 2 :(得分:1)

您的方法可能还可以,但是您可能遇到的问题是,从数据框中获取数组或列表之后,您得到了一个嵌套列表,即。 [['牛','青蛙',nan,'狗']]。注意双括号。您需要摆脱括号对。尝试类似y = x [0]的操作。然后再次运行您的nan删除代码。