在pandas中的数据框中查找非数字行?

49 python dataframe pandas

我在pandas中有一个大型数据框,除了用作索引的列之外,它应该只有数值:

df = pd.DataFrame({'a': [1, 2, 3, 'bad', 5],
                   'b': [0.1, 0.2, 0.3, 0.4, 0.5],
                   'item': ['a', 'b', 'c', 'd', 'e']})
df = df.set_index('item')
Run Code Online (Sandbox Code Playgroud)

如何找到df其中包含非数字值的数据帧行?

在这个例子中它的第四行中的数据帧,它具有串'bad'a列.如何以编程方式找到这一行?

And*_*den 58

您可以使用np.isreal检查每个元素的类型(applymap将函数应用于DataFrame中的每个元素):

In [11]: df.applymap(np.isreal)
Out[11]:
          a     b
item
a      True  True
b      True  True
c      True  True
d     False  True
e      True  True
Run Code Online (Sandbox Code Playgroud)

如果行中的所有内容都为True,那么它们都是数字:

In [12]: df.applymap(np.isreal).all(1)
Out[12]:
item
a        True
b        True
c        True
d       False
e        True
dtype: bool
Run Code Online (Sandbox Code Playgroud)

所以要获取rouges的subDataFrame,(注意:上面的否定,〜,找到至少有一个非数字的流氓):

In [13]: df[~df.applymap(np.isreal).all(1)]
Out[13]:
        a    b
item
d     bad  0.4
Run Code Online (Sandbox Code Playgroud)

你也可以找到你可以使用argmin第一个罪犯的位置:

In [14]: np.argmin(df.applymap(np.isreal).all(1))
Out[14]: 'd'
Run Code Online (Sandbox Code Playgroud)

正如@CTZhu指出的那样,检查它是int还是float 的实例可能会稍快一点(np.isreal会有一些额外的开销):

df.applymap(lambda x: isinstance(x, (int, float)))
Run Code Online (Sandbox Code Playgroud)

  • 大!只有`df.applymap(lambda x:isinstance(x,(int,float)))`将大约快18%.使用带有内置方法的`lambda`有时候相当快. (2认同)
  • 值得注意的是 `np.isreal(None) 不是 True` (2认同)
  • 如何只检查一列中的非数字值? (2认同)
  • @Superdooperhero在列上使用.apply而不在DataFrame上使用.applymap,即`df [“ a”]。apply(np.isreal)和`df [〜df [“ a”]。apply(np.isreal) ]` (2认同)

Ped*_*rte 14

已经对这个问题有了一些很好的答案,但是这里有一个很好的片段,如果它们在某些列上有非数字值,我会定期使用它来删除行:

# Eliminate invalid data from dataframe (see Example below for more context)

num_df = (df.drop(data_columns, axis=1)
         .join(df[data_columns].apply(pd.to_numeric, errors='coerce')))

num_df = num_df[num_df[data_columns].notnull().all(axis=1)]
Run Code Online (Sandbox Code Playgroud)

它的工作方式是我们首先从中获取drop所有内容,然后使用a 将它们传递回来(使用选项,以便将所有非数字条目转换为).结果保存到. data_columnsdfjoinpd.to_numeric'coerce'NaNnum_df

在第二行,我们使用一个过滤器,只保留所有值都不为空的行.

请注意,这pd.to_numeric是强制NaN转换为无法转换为数值的所有内容,因此不会删除表示数值的字符串.例如,'1.25'将被识别为数值1.25.

免责声明:pd.to_numeric是在熊猫版中引入的0.17.0

例:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame({"item": ["a", "b", "c", "d", "e"],
   ...:                    "a": [1,2,3,"bad",5],
   ...:                    "b":[0.1,0.2,0.3,0.4,0.5]})

In [3]: df
Out[3]: 
     a    b item
0    1  0.1    a
1    2  0.2    b
2    3  0.3    c
3  bad  0.4    d
4    5  0.5    e

In [4]: data_columns = ['a', 'b']

In [5]: num_df = (df
   ...:           .drop(data_columns, axis=1)
   ...:           .join(df[data_columns].apply(pd.to_numeric, errors='coerce')))

In [6]: num_df
Out[6]: 
  item   a    b
0    a   1  0.1
1    b   2  0.2
2    c   3  0.3
3    d NaN  0.4
4    e   5  0.5

In [7]: num_df[num_df[data_columns].notnull().all(axis=1)]
Out[7]: 
  item  a    b
0    a  1  0.1
1    b  2  0.2
2    c  3  0.3
4    e  5  0.5
Run Code Online (Sandbox Code Playgroud)


CT *_*Zhu 6

对于混乱感到抱歉,这应该是正确的方法.你只想捕捉'bad',而不是像'good'; 或者只是任何非数值?

In[15]:
np.where(np.any(np.isnan(df.convert_objects(convert_numeric=True)), axis=1))
Out[15]:
(array([3]),)
Run Code Online (Sandbox Code Playgroud)


mat*_*tiu 5

# Original code
df = pd.DataFrame({'a': [1, 2, 3, 'bad', 5],
                   'b': [0.1, 0.2, 0.3, 0.4, 0.5],
                   'item': ['a', 'b', 'c', 'd', 'e']})
df = df.set_index('item')
Run Code Online (Sandbox Code Playgroud)

使用'coerce' 转换为数值,并用'nan'填充错误值

a = pd.to_numeric(df.a, errors='coerce')
Run Code Online (Sandbox Code Playgroud)

使用isna返回布尔值索引:

idx = a.isna()
Run Code Online (Sandbox Code Playgroud)

将该索引应用于数据框:

df[idx]
Run Code Online (Sandbox Code Playgroud)

输出

返回其中包含错误数据的行:

        a    b
item          
d     bad  0.4
Run Code Online (Sandbox Code Playgroud)


dya*_*ang 5

我在想,只是给出一个想法,将列转换为字符串,并且使用字符串更容易。但是,这不适用于包含数字的字符串,例如bad123. 并且~正在取选择的补集。

df['a'] = df['a'].astype(str)
df[~df['a'].str.contains('0|1|2|3|4|5|6|7|8|9')]
df['a'] = df['a'].astype(object)
Run Code Online (Sandbox Code Playgroud)

并使用'|'.join([str(i) for i in range(10)])来生成'0|1|...|8|9'

或使用np.isreal()函数,就像得票最多的答案一样

df[~df['a'].apply(lambda x: np.isreal(x))]
Run Code Online (Sandbox Code Playgroud)