【问题标题】:How to tag corrupted data in dataframe after an error has been raised引发错误后如何在数据框中标记损坏的数据
【发布时间】:2017-09-13 12:04:33
【问题描述】:

我有一个大型数据框,其中包含一个(挪威)社会安全号码。可以通过特殊算法从这个数字中获取出生日期。然而,非法的社会安全号码不时地潜入数据库,破坏计算。

我想做的是标记具有非法社会安全号码的每一行,以及显示所引发错误的日志消息。

考虑以下构造的示例

import pandas as pd
from datetime import date

sample_data = pd.DataFrame({'id' : [1, 2, 3], \
                            'sec_num' : [19790116, 19480631, 19861220]})


# The actual algorithm transforming the sec number is more complicated
# this is just for illustration purposes
def int2date(argdate: int):

    try:
        year = int(argdate / 10000)
        month = int((argdate % 10000) / 100)
        day = int(argdate % 100)
        return date(year, month, day)
    except ValueError:
        raise ValueError("Value:{0} not a legal date.".format(argdate))

我想创建以下输出

   id   sec_num date_of_birth  is_in_error                    error_msg
0   1  19790116    1979-01-16        False  
1   2  19480631          None         True 19480631 is not a legal date         
2   3  19861220    1986-12-20        False 

我试过了

try:
    sample_data['date_of_birth'] = [int2date(sec_num) for \
                   sec_num in sample_data['sec_num']]
    sample_data['is_in_error'] = False
    sample_data['error_msg'] = ''
 except ValueError as e:
    sample_data['is_in_error'] = True
    sample_data['error_msg'] = str(e)

但这会产生这个

   id   sec_num  is_in_error                         error_msg
0   1  19790116         True  Value:19480631 not a legal date.
1   2  19480631         True  Value:19480631 not a legal date.
2   3  19861220         True  Value:19480631 not a legal date.

我想问题是我在一个操作中分配了date_of_birth-column,而在另一个操作中分配了错误。我不确定如何模拟地捕获和创建is_in_errorerror_msg 列。

【问题讨论】:

  • 对不起,您能否发布一个真实的数据样本以及您的真实算法实际上是什么,目前即使这是一个字符串,6 月 31 日也不是有效日期
  • 我不确定我是否理解您的要求。该算法正确执行,它创建一个日、月和年变量,然后根据这些值日期(年、月、日)创建一个日期。当无效的社会安全号码产生非法日期时,就会出现问题。在这个例子中,我只是直接跳到了非法日期。
  • 你为什么不直接做df['date_of_birth'] = pd.to_datetime(df['sec_num'].astype(str), format='%Y%M%D'm errors='coerce') 这会将NaT 放在你有无效日期的地方。本质上,当您执行sample_data[some_col] = some_val 时,您正在做的事情是将整列设置为该值而不是特定行
  • 好吧,我明白为什么输入整个算法很有价值......实际的社会安全号码是 11 位数字,你不能使用 pd.to_datetime 。所以我首先必须从算法中返回一个字符串或整数,然后再进行转换。

标签: python pandas error-handling


【解决方案1】:

发生这种情况是因为您填充数据框的方式。

sample_data['error_msg'] = str(e)

实际上会用str(e) 覆盖整个列。

这可能是最有效的方法:

def int2date(argdate: int):

    try:
        year = int(argdate / 10000)
        month = int((argdate % 10000) / 100)
        day = int(argdate % 100)
        return date(year, month, day)
    except ValueError as e:
        pass # you could write the row and the error to your logs here

df['date_of_birth'] = df.sec_num.apply(int2date)
df['is_in_error'] = df.date_of_birth.isnull()

但是,如果您还想将错误写入数据帧,您可以使用这种方法,尽管它可能会慢得多(可能有更快的解决方案)。

df['date_of_birth'] = None
df['error_msg'] = None
df['is_in_error'] = False
for i, row in df.iterrows():
    try:
        date_of_birth = int2date(row['sec_num'])
        df.set_value(i, 'date_of_birth', date_of_birth)
    except ValueError as e:
        df.set_value(i, 'is_in_error', True)
        df.set_value(i, 'error_msg', str(e))

这会单独处理每一行,并且只会将错误写入正确的索引,而不是更新整个列。

【讨论】:

  • 你的第二种方式是推荐的pandas方式(function+apply)。第一种方法还可以,但会很慢(而且你需要大写 true & false)。一般来说,您希望避免迭代,除非作为绝对的最后手段。如果您愿意,我建议您删除答案的上半部分并保留下半部分。
  • 只是一个观察,关于你答案的第二部分,在有效的 Python 中(对于那些有那本书的副本的人)它指出返回 None 是不好的形式。这让我有点恼火,因为 JohnE 的评论也是正确的:|
  • 感谢@JohnE 的输入,我相应地更改了答案。我还将函数更改为不返回None
【解决方案2】:

您正处于处理大数据的领域。从循环中抛出异常通常不是最好的主意,因为它通常会中止循环。与其他许多人一样,您似乎并不想要那样。

为了实现这一点,一种典型的方法是使用一个不抛出异常但返回异常的函数。

def int2date(argdate: int):
    try:
        year = int(argdate / 10000)
        month = int((argdate % 10000) / 100)
        day = int(argdate % 100)
        return date(year, month, day)
    except ValueError:
        return ValueError("Value:{0} not a legal date.".format(argdate))

有了这个,您可以简单地将一个值列表映射到函数,并将异常(当然缺少跟踪,但在这种情况下这不应该成为问题)作为结果列表中的值:

然后,您可以遍历列表,将找到的异常替换为 None 值,然后用异常中包含的消息填充其他列。

【讨论】:

    猜你喜欢
    • 2014-03-18
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 2019-01-31
    • 2015-02-04
    相关资源
    最近更新 更多