[英]Remove non-numeric rows in one column with pandas
有一個如下所示的數據框,它有一個不干凈的列“id”,它應該是數字列
id, name
1, A
2, B
3, C
tt, D
4, E
5, F
de, G
是否有一種簡潔的方法來刪除行,因為 tt 和 de 不是數值
tt,D
de,G
使數據框干凈?
id, name
1, A
2, B
3, C
4, E
5, F
使用pd.to_numeric
In [1079]: df[pd.to_numeric(df['id'], errors='coerce').notnull()]
Out[1079]:
id name
0 1 A
1 2 B
2 3 C
4 4 E
5 5 F
您可以使用字符串isnumeric
的標准方法並將其應用於id
列中的每個值:
import pandas as pd
from io import StringIO
data = """
id,name
1,A
2,B
3,C
tt,D
4,E
5,F
de,G
"""
df = pd.read_csv(StringIO(data))
In [55]: df
Out[55]:
id name
0 1 A
1 2 B
2 3 C
3 tt D
4 4 E
5 5 F
6 de G
In [56]: df[df.id.apply(lambda x: x.isnumeric())]
Out[56]:
id name
0 1 A
1 2 B
2 3 C
4 4 E
5 5 F
或者,如果您想使用id
作為索引,您可以這樣做:
In [61]: df[df.id.apply(lambda x: x.isnumeric())].set_index('id')
Out[61]:
name
id
1 A
2 B
3 C
4 E
5 F
盡管pd.to_numeric
的情況沒有使用apply
方法,但它幾乎比對str
列應用np.isnumeric
慢兩倍。 我還添加了使用 pandas str.isnumeric
的選項,該選項比使用pd.to_numeric
輸入更少,而且速度更快。 但是pd.to_numeric
更通用,因為它可以處理任何數據類型(不僅僅是字符串)。
df_big = pd.concat([df]*10000)
In [3]: df_big = pd.concat([df]*10000)
In [4]: df_big.shape
Out[4]: (70000, 2)
In [5]: %timeit df_big[df_big.id.apply(lambda x: x.isnumeric())]
15.3 ms ± 2.02 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [6]: %timeit df_big[df_big.id.str.isnumeric()]
20.3 ms ± 171 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [7]: %timeit df_big[pd.to_numeric(df_big['id'], errors='coerce').notnull()]
29.9 ms ± 682 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
鑒於df
是您的數據框,
import numpy as np
df[df['id'].apply(lambda x: isinstance(x, (int, np.int64)))]
它所做的是將id
列中的每個值傳遞給isinstance
函數並檢查它是否為int
。 然后它返回一個布爾數組,最后只返回存在True
的行。
如果您還需要考慮float
值,另一種選擇是:
import numpy as np
df[df['id'].apply(lambda x: type(x) in [int, np.int64, float, np.float64])]
請注意,任何一種方式都不是就地的,因此您需要將其重新分配給原始 df,或創建一個新的:
df = df[df['id'].apply(lambda x: type(x) in [int, np.int64, float, np.float64])]
# or
new_df = df[df['id'].apply(lambda x: type(x) in [int, np.int64, float, np.float64])]
當x
為float
類型時, x.isnumeric()
不會測試返回True
。
過濾掉可以轉換為float
的值的一種方法:
df[df['id'].apply(lambda x: is_float(x))]
def is_float(x):
try:
float(x)
except ValueError:
return False
return True
這個怎么樣? .str
訪問器是我的最愛之一 :)
import pandas as pd
df = pd.DataFrame(
{
'id': {0: '1', 1: '2', 2: '3', 3: 'tt', 4: '4', 5: '5', 6: 'de'},
'name': {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G'}
}
)
df_clean = df[df.id.str.isnumeric()]
補充 (2021-06-22)
如果id
包含某種令人頭疼的東西(例如float
、 None
、 nan
),您可以使用astype('str')
將它們強制轉換為str
數據類型。
import numpy as np
import pandas as pd
df = pd.DataFrame(
{
'id': {0: '1', 1: '2', 2: '3', 3: 3.14, 4: '4', 5: '5', 6: None, 7: np.nan},
'name': {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'E', 5: 'F', 6: 'G', 7: 'H'}
}
)
df_clean = df[df.id.astype('str').str.isnumeric()]
原始的,但它仍然有效。
這是一種動態方法,僅適用於 int64 和 float 64,如果您的數據框中有其他數字數據類型,請確保將它們添加到 if 語句
# make dataframe of column data types
col_types = df.dtypes.to_frame()
col_types.columns = ['dtype']
#make list of zeros
drop_it = [0]*col_types.shape[0]
k = 0
#make it a one if the data isn't numeric
#if you have other numeric types you need to add them to if statement
for t in col_types.dtype:
if t != 'int64' and t != 'float64':
drop_it[k] = 1
k = k + 1
#delete types from drop list that aren't numeric
col_types['drop_it'] = drop_it
col_types = col_types.loc[col_types["drop_it"] == 1]
#finally drop columns that are in drop list
for col_to_drop in col_types.index.values.tolist():
df = df.drop([col_to_drop], axis = 1)
另一種選擇是使用query
方法:
In [5]: df.query('id.str.isnumeric()')
Out[5]:
id name
0 1 A
1 2 B
2 3 C
4 4 E
5 5 F
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.