熊猫:放下行,如果超过一半的列是NaN

时间:2017-09-26 18:39:09

标签: python pandas

我有一个名为df的Pandas DataFrame,包含1,460行和81列。我想删除所有至少有一半条目为NaN的列,并为行做类似的事情。

从Pandas文档中,我尝试了这个:

train_df.shape //(1460, 81)
train_df.dropna(thresh=len(train_df)/2, axis=1, inplace=True)
train_df.shape //(1460, 77)

这是正确的做法吗?它似乎删除了4列,但我很惊讶。我原以为len(train_df)会得到行数,所以我将错误的值传递给thresh ......?

我如何对行执行相同操作(删除至少有一半列为NaN的行)?

谢谢!

4 个答案:

答案 0 :(得分:3)

使用countloccount(axis=)会忽略NaN来计算。

In [4135]: df.loc[df.count(1) > df.shape[1]/2, df.count(0) > df.shape[0]/2]
Out[4135]:
          0
0  0.382991
1  0.428040
7  0.441113

详细

In [4136]: df
Out[4136]:
          0         1         2         3
0  0.382991  0.658090  0.881214  0.572673
1  0.428040  0.258378  0.865269  0.173278
2  0.579953       NaN       NaN       NaN
3  0.117927       NaN       NaN       NaN
4  0.597632       NaN       NaN       NaN
5  0.547839       NaN       NaN       NaN
6  0.998631       NaN       NaN       NaN
7  0.441113  0.527205  0.779821  0.251350

In [4137]: df.count(1) > df.shape[1]/2
Out[4137]:
0     True
1     True
2    False
3    False
4    False
5    False
6    False
7     True
dtype: bool

In [4138]: df.count(0) < df.shape[0]/2
Out[4138]:
0    False
1     True
2     True
3     True
dtype: bool

答案 1 :(得分:2)

设置

np.random.seed([3,14159])
df = pd.DataFrame(np.random.choice([1, np.nan], size=(10, 10)))

df

     0    1    2    3    4    5    6    7    8    9
0  1.0  1.0  NaN  NaN  NaN  1.0  1.0  NaN  1.0  NaN
1  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0  NaN  1.0
2  NaN  1.0  1.0  NaN  NaN  NaN  NaN  1.0  1.0  1.0
3  1.0  NaN  NaN  NaN  NaN  NaN  NaN  NaN  1.0  NaN
4  1.0  1.0  1.0  1.0  1.0  1.0  NaN  NaN  1.0  NaN
5  1.0  NaN  NaN  1.0  NaN  NaN  1.0  NaN  NaN  1.0
6  NaN  NaN  1.0  NaN  NaN  1.0  1.0  NaN  NaN  1.0
7  NaN  NaN  NaN  1.0  NaN  1.0  NaN  1.0  NaN  NaN
8  1.0  1.0  1.0  NaN  1.0  NaN  1.0  NaN  NaN  1.0
9  NaN  NaN  NaN  1.0  1.0  1.0  1.0  1.0  1.0  1.0

解决方案1 ​​
这假设您在删除行或列之前计算行和列。

n = df.notnull()

df.loc[n.mean(1) > .5, n.mean() > .5]

     5    6    9
1  1.0  1.0  1.0
4  1.0  NaN  NaN
8  NaN  1.0  1.0
9  1.0  1.0  1.0

解决方案2
类似的概念,但使用numpy工具。

v = np.isnan(df.values)

r = np.count_nonzero(v, 1) < v.shape[1] // 2
c = np.count_nonzero(v, 0) < v.shape[0] // 2
df.loc[r, c]

     5    6    9
1  1.0  1.0  1.0
4  1.0  NaN  NaN
8  NaN  1.0  1.0
9  1.0  1.0  1.0

答案 2 :(得分:2)

我猜您做对了,但是忘记添加.index。 该行应如下所示:

train_df.dropna(thresh=len(train_df.index)/2, axis=1, inplace=True)

希望有帮助。

答案 3 :(得分:0)

尝试此代码,它将成功!

df.dropna(thresh = df.shape[1]/3, axis = 0, inplace = True)