[英]Finding non-numeric rows in dataframe in pandas?
我在 pandas 中有一個大的 dataframe,除了用作索引的列應該只有數值:
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')
如何找到 dataframe df
中包含非數字值的行?
在此示例中,它是 dataframe 中的第四行,其a
列中包含字符串'bad'
。 如何以編程方式找到這一行?
您可以使用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
如果該行中的所有均為True,則它們都是數字:
In [12]: df.applymap(np.isreal).all(1)
Out[12]:
item
a True
b True
c True
d False
e True
dtype: bool
因此,要獲得路由的subDataFrame,(請注意:上面的否定〜會找到至少具有一個非流氓非數字字符的那些):
In [13]: df[~df.applymap(np.isreal).all(1)]
Out[13]:
a b
item
d bad 0.4
您還可以找到可以使用argmin的第一個罪犯的位置:
In [14]: np.argmin(df.applymap(np.isreal).all(1))
Out[14]: 'd'
正如@CTZhu指出的那樣, 檢查它是int還是float 的實例可能會稍快一些(np.isreal會有一些額外的開銷):
df.applymap(lambda x: isinstance(x, (int, float)))
對於這個問題已經有了一些不錯的答案,但是如果有行在某些列上使用非數字值,我會定期使用它來刪除行:
# 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)]
該方法這是工作,我們首先drop
所有data_columns
從df
,然后用join
到將它們放回使它們通過后pd.to_numeric
(與選項'coerce'
,這樣所有非數字輸入轉換為NaN
)。 結果保存到num_df
。
在第二行中,我們使用一個過濾器,該過濾器僅保留所有值都不為null的行。
請注意, pd.to_numeric
將所有無法轉換為數字值的內容強制轉換為NaN
,因此不會刪除表示數字值的字符串。 例如, '1.25'
將被識別為數值1.25
。
免責聲明: pd.to_numeric
在pandas版本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
抱歉,這是正確的方法。 您是否只想捕捉'bad'
,而不是'good'
? 還是只是任何非數字值?
In[15]:
np.where(np.any(np.isnan(df.convert_objects(convert_numeric=True)), axis=1))
Out[15]:
(array([3]),)
# 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')
使用'coerce' 轉換為數值,並用'nan'填充錯誤值
a = pd.to_numeric(df.a, errors='coerce')
使用isna返回布爾值索引:
idx = a.isna()
將該索引應用於數據框:
df[idx]
返回其中包含錯誤數據的行:
a b
item
d bad 0.4
如果您正在使用帶有字符串值的列,則可以使用非常有用的函數series.str.isnumeric(),例如:
a = pd.Series(['hi','hola','2.31','288','312','1312', '0,21', '0.23'])
我要做的是將該列復制到新列,並執行str.replace('。','')和str.replace(',',''),然后選擇數值。 和:
a = a.str.replace('.','')
a = a.str.replace(',','')
a.str.isnumeric()
Out [15]:0錯誤1錯誤2對3對4對5對6對6對7對dtype:bool
祝你好運!
我在想類似的東西,只是給出一個想法,即可將列轉換為字符串,並且使用字符串更容易。 但是,這不適用於包含數字的字符串,例如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)
並使用'|'.join([str(i) for i in range(10)])
生成'0|1|...|8|9'
或使用np.isreal()
函數,就像投票最多的答案一樣
df[~df['a'].apply(lambda x: np.isreal(x))]
以上所有精彩評論一定能解決 99% 的情況,但如果您仍然遇到問題,請同時檢查您是否轉換了數據類型。
有時我強制數據鍵入 float16 以保存 memory。使用:
df[col] = df[col].astype(np.float16)
但這可能會悄悄地破壞你的代碼。 因此,如果您進行了任何類型的數據類型轉換,請仔細檢查是否存在溢出。 禁用轉換並重試。
它對我有用!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.