【问题标题】:pandas select rows where datetime error occurs熊猫选择发生日期时间错误的行
【发布时间】:2019-12-15 08:26:25
【问题描述】:

我需要在数据框 (https://pastebin.com/kNqLtUWu) 内对 dates 执行验证,检查 date 是否有效。如果date 无效(即pd.to_datetime 无法解析 - 0107-01-06,例如),我需要用Yes 填充Fail 列。

我对包含日期的列进行了子集化,并且能够识别包含无效日期的列并将它们添加到字典中,但还没有弄清楚如何返回特定的行。

我对其他方法持开放态度,但我需要使用 pandas 并最终以 Fail 列指示行,我计划在该行上过滤最终数据帧(一个数据帧包含日期错误的行,另一个没有错误)。

完整代码见 pastebin 链接

# insert empty Fail column to identify date errors
df.insert(loc=0, column='Fail', value="")

# replace all blanks with np.NaN
df.replace(r"^s*$", np.nan, regex=True, inplace = True)

# get list of date columns
cols = list(df)
date_cols = cols[2:]

# create empty dict
dfs = {}

# iterate over date columns to identify which columns contain invalid dates & add to dfs
for col in df[date_cols]:
    try:
        df[col] = df[col].apply(pd.to_datetime, errors='raise')
    except:
        print("%s column contains invalid date" % col)
        dfs[col] = df[col]

【问题讨论】:

  • 无需尝试:df[col] = pd.to_datetime(df[col], errors='coerce') 为您提供pd.NaT,其中to_datetime 失败。
  • @QuangHoang,我需要知道哪些值不能解析为日期,以便为这些行填充 Fail 列。强制将替换所有无法解析为 NaT 日期的值,甚至是 NaN。即使我没有用 NaN 替换空白也是如此。所以我不确定这将如何帮助确定行?

标签: python-3.x pandas datetime


【解决方案1】:

您所描述的问题可以通过coerce 和一点逻辑来解决:

# original non_null
notnull = df[col].notnull()

# where to_datetime fails
not_datetime = pd.to_datetime(df[col], errors='coerce').isna()

not_datetime = not_datetime & notnull

【讨论】:

  • 我之前接受的答案没有捕捉到所有非日期,所以我尝试了你的解决方案并且它有效。谢谢。
  • 这是一个很好的解决方案,谢谢!
【解决方案2】:

IIUC,您关心的是创建Fail 列。所以,我专注于创造它。 我认为您可以在日期时间列上使用apply 来实现它,并使用自定义 lambda 在轴 = 1 上进行切片。 lambda 将过滤掉 NaN,然后将每个切片传递给 pd.to_datetimecoerce,并检查输出中的任何 NaT

df['Fail'] = (df[date_cols].apply(lambda x: pd.to_datetime(x[x.notna()], errors='coerce')
                          .isna().any(), axis=1).replace({True: 'Fail', False: ''}))

Out[869]:
    Fail patient_ID DateOfBirth  ...    date_10    date_11     date_12
0              A001  1950-03-02  ...        NaT        NaT         NaN
1              A001  1950-03-02  ...        NaT        NaT         NaN
2              A001  1950-03-02  ...        NaT        NaT         NaN
3              A001  1950-03-02  ...        NaT        NaT         NaN
4              A001  1950-03-02  ... 2010-01-01        NaT         NaN
5              A001  1950-03-02  ...        NaT 2010-01-01         NaN
6              A001  1950-03-02  ...        NaT        NaT    1/1/2010
7              A001  1950-03-02  ...        NaT        NaT    1/1/2010
8              A001  1950-03-02  ...        NaT        NaT    1/1/2010
9              A001  1950-03-02  ...        NaT        NaT    1/1/2010
10             A001  1950-03-02  ...        NaT        NaT    1/1/2010
11             A001  1950-03-02  ...        NaT        NaT    1/1/2010
12             A001  1950-03-02  ...        NaT        NaT    1/1/2010
13             A001  1950-03-02  ...        NaT        NaT    1/1/2010
14             A001  1950-03-02  ...        NaT        NaT    1/1/2010
15  Fail       A002  1950-03-02  ...        NaT        NaT         NaN
16             A002  1950-03-02  ...        NaT        NaT         NaN
17             A002  1950-03-02  ...        NaT        NaT         NaN
18             A002  1950-03-02  ...        NaT        NaT         NaN
19             A002  1950-03-02  ... 2010-01-01        NaT         NaN
20             A002  1950-03-02  ...        NaT 2010-01-01         NaN
21             A002  1950-03-02  ...        NaT        NaT    1/1/2010
22             A002  1950-03-02  ...        NaT        NaT    1/1/2010
23             A002  1950-03-02  ...        NaT        NaT    1/1/2010
24             A002  1950-03-02  ...        NaT        NaT    1/1/2010
25             A002  1950-03-02  ...        NaT        NaT    1/1/2010
26             A002  1950-03-02  ...        NaT        NaT    1/1/2010
27             A002  1950-03-02  ...        NaT        NaT    1/1/2010
28             A002  1950-03-02  ...        NaT        NaT    1/1/2010
29  Fail       A002  1950-03-02  ...        NaT        NaT  0107-01-06

[30 rows x 15 columns]

注意
上面的代码用于创建 Fail 列。它不会将这些列转换为日期时间。要转换它们,您只需单独致电pd.to_datetime


下面是两行的值,其中Fail

In [870]: df.loc[15]
Out[870]:
Fail                          Fail
patient_ID                    A002
DateOfBirth    1950-03-02 00:00:00
date_1                  0107-01-06
date_2         2010-01-01 00:00:00
date_3                         NaT
date_4                         NaT
date_5                         NaT
date_6                         NaT
date_7                         NaT
date_8                         NaT
date_9                         NaT
date_10                        NaT
date_11                        NaT
date_12                        NaN
Name: 15, dtype: object

In [871]: df.loc[29]
Out[871]:
Fail                          Fail
patient_ID                    A002
DateOfBirth    1950-03-02 00:00:00
date_1                         NaN
date_2                         NaT
date_3                         NaT
date_4                         NaT
date_5                         NaT
date_6                         NaT
date_7                         NaT
date_8                         NaT
date_9                         NaT
date_10                        NaT
date_11                        NaT
date_12                 0107-01-06
Name: 29, dtype: object

【讨论】:

  • 谢谢!效果很好
  • 实际上发现了一些没有转换的情况,所以我选择了@Quang Hoang 实现。
猜你喜欢
  • 1970-01-01
  • 2021-01-12
  • 2018-12-01
  • 1970-01-01
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
  • 1970-01-01
相关资源
最近更新 更多