我正在使用pd.read_csv
从外部数据源读取csv文件,如下面的代码所示:
pd.read_csv(
BytesIO(raw_data),
parse_dates=['dates'],
date_parser=np.datetime64,
)
但是,在发送的csv中,有一个格式错误的日期,导致以下错误:
ValueError: Error parsing datetime string "2015-08-2" at position 8
这会导致整个应用程序崩溃。当然,我可以通过try / except来处理这种情况,但之后我将丢失该特定csv中的所有其他数据。我需要pandas来保存和解析其他数据。
我无法预测此数据(每日更改)何时/何处将具有格式错误的日期。是否有某种方法可以让pd.read_csv
只跳过日期不好的行但是仍然解析csv中的所有其他行?
答案 0 :(得分:4)
在发送的csv中,有一个格式错误的日期
np.datetime64
需要ISO8601 formatted个字符串才能正常运行。好消息是,您可以将np.datetime64
包装在自己的函数中,并将其用作date_parser
:
def parse_date(v):
try:
return np.datetime64(v)
except:
# apply whatever remedies you deem appropriate
pass
return v
pd.read_csv(
...
date_parser=parse_date
)
我需要pandas来保存和解析其他数据。
我经常发现像dateutil
这样更灵活的日期解析器比np.datetime64
效果更好,甚至可以在没有额外功能的情况下工作:
import dateutil
pd.read_csv(
BytesIO(raw_data),
parse_dates=['dates'],
date_parser=dateutil.parser.parse,
)
答案 1 :(得分:1)
这是使用pd.convert_objects()方法执行此操作的另一种方法:
# make good and bad date csv files
# read in good dates file using parse_dates - no problem
df = pd.read_csv('dategood.csv', parse_dates=['dates'], date_parser=np.datetime64)
df.dtypes
dates datetime64[ns]
data float64
dtype: object
# try same code on bad dates file - throws exceptions
df = pd.read_csv('datebad.csv', parse_dates=['dates'], date_parser=np.datetime64)
ValueError: Error parsing datetime string "Q%Bte0tvk5" at position 0
# read the file first without converting dates
# then use convert objects to force conversion
df = pd.read_csv('datebad.csv')
df['cdate'] = df.dates.convert_objects(convert_dates='coerce')
# resulting new date column is a datetime64 same as good data file
df.dtype
dates object
data float64
cdate datetime64[ns]
dtype: object
# the bad date has NaT in the cdate column - can clean it later
df.head()
dates data cdate
0 2015-12-01 0.914836 2015-12-01
1 2015-12-02 0.866848 2015-12-02
2 2015-12-03 0.103718 2015-12-03
3 2015-12-04 0.514086 2015-12-04
4 Q%Bte0tvk5 0.583617 NaT
答案 2 :(得分:0)
使用内置的pd.to_datetime
,它将非日期类型的数据转换为NaT
pd.read_csv(
BytesIO(raw_data),
parse_dates=['dates'],
date_parser=pd.to_datetime,
)
现在您可以使用标准的nan /空值检查来过滤掉无效的行
df = df[~df["dates"].isnull()]