使用pd.read_csv时跳过包含错误日期的行

时间:2015-12-24 22:49:01

标签: python csv pandas

我正在使用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中的所有其他行?

3 个答案:

答案 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()]