我正在分析来自工业控制系统的数据,该系统以1秒的间隔将传感器数据记录到CSV文件。我们每周做一次分析,所以CSV文件很大(49列x ~600k行)。有时(可能是由于字段停电),CSV文件有损坏的行。我们得到列数正确但数据类型错误的行。下面是一个虚拟DF,以较小的规模说明了这个问题:
mydict = {'colFloat': [1.5, 2.3, 'TRUE', 'FALSE', 3.5, 7.8], 'colBool': ['FALSE', 'TRUE', 3.2, 1.1, 'TRUE', 'TRUE'], 'colInt': [2, 2, 3.7, 9.9, 1, 4]}
df = pd.DataFrame(data = mydict)
在这个例子中,'colFloat'应该是dtype float64, 'colBool'应该是dtype bool, 'colInt'应该是dtype int64,但是当然中间的两行错误导致所有三列都是object类型。后来,当我尝试做组比和集成传感器读数(例如来自'colFloat')时,我得到一个错误,因为列中的非float数据会导致问题。
我想要一个方法,我可以在df上运行,这将删除错误的行,并通知我它们存在。在我上面的例子中,结果df看起来像这样df:
mydictclean = {'colFloat': [1.5, 2.3, 3.5, 7.8], 'colBool': ['FALSE', 'TRUE', 'TRUE', 'TRUE'], 'colInt': [2, 2, 1, 4]}
dfclean = pd.DataFrame(data = mydictclean)
我尝试在read_csv调用中使用dtype参数指定dtypes,但是当函数遇到坏行时,会抛出错误。谢谢你的帮助!
您可以使用一组转换器,然后删除具有nan的行:
types = {'colFloat': 'numeric', 'colInt': 'numeric', 'colBool': 'boolean'}
converter = {'numeric': lambda s: pd.to_numeric(s, errors='coerce'),
'boolean': lambda s: s.str.upper().map({'TRUE': True, 'FALSE': False})
}
dfclean = pd.DataFrame(index=df.index)
for c, t in types.items():
dfclean[c] = converter[t](df[c])
dfclean = dfclean.dropna()
print(dfclean)
输出:
colFloat colInt colBool
0 1.5 2.0 False
1 2.3 2.0 True
4 3.5 1.0 True
5 7.8 4.0 True
NB。对于int/float,使用pandas维护它并不总是那么容易。您可以使用convert_dtypes
执行自动化(安全)浮动→
我会尝试在所有列中同时捕获所有类型错误和CONVERT。
参见如何检查字符串是否为数字(float)?对于第一个函数:
def is_number(n):
is_number = True
try:
num = float(n)
# check for "nan" floats
is_number = num == num # or use `math.isnan(num)`
except ValueError:
is_number = False
return is_number
然后你自己的:
def check_and_convert_int(x):
if x.is_integer():
return int(x)
else:
return np.nan
def check_and_convert_bool(x):
if x in [True, 'True', 'TRUE']:
return True
elif x in [False, 'False', 'FALSE']:
return False
else:
return np.nan
def check_and_convert_float(x):
if is_number(x):
return float(x)
else:
return np.nan
那么我会做:
df['int_col_clean'] = df['int_col'].apply(lambda x: check_and_convert_int(x))
df['bool_col_clean'] = df['bool_col'].apply(lambda x: check_and_convert_bool(x))
df['float_col_clean'] = df['float_col'].apply(lambda x: check_and_convert_float(x))
检查可能被删除的列:
df[df.isna().any(axis=1)]
如果一切正常,把它们丢掉:
df = df.dropna(subset = ['int_col_clean', 'bool_col_clean', 'float_col_clean'])
我必须改变布尔值,因为它们现在的方式是字符串:
mydict = {'colFloat': [1.5, 2.3,'TRUE', 'FALSE', 3.5, 7.8], 'colBool': [False, True, 3.2, 1.1, True, True], 'colInt': [2, 2, 3.7, 9.9, 1, 4]}
df = pd.DataFrame(data = mydict)
然后你可以根据实例类型进行过滤:
df = df[df['colFloat'].apply(isinstance, args=[float])]
df = df[df['colBool'].apply(isinstance, args=[bool])]
df['colInt'] = df['colInt'].astype(int)
df = df[df['colInt'].apply(isinstance, args=[int])]
df
输出:
colFloat colBool colInt
0 1.5 False 2
1 2.3 True 2
4 3.5 True 1
5 7.8 True 4
try this:
df.loc[(df.colFloat.apply(lambda x: type(x) == float)) ]
但是你的boolcol不是bool。