美文网首页
数据分析工作中遇到的一些BUG,解决方案及反思(Python)

数据分析工作中遇到的一些BUG,解决方案及反思(Python)

作者: Guang777 | 来源:发表于2023-06-18 14:15 被阅读0次

    类型转换相关

    TypeError: cannot safely cast non-equivalent float64 to uint16

    报错原因:

    将 "input_address_cnt"(该交易的输入地址数), "addressCnt"(该实体包含的地址数)转换成 UInt16时报错:TypeError: cannot safely cast non-equivalent float64 to uint16

    # 将 int 类型的列转换成无符号整型
    for int_col in ["input_address_cnt", "addressCnt"]:
        spv_node_info_batch[int_col] = pd.to_numeric(
            spv_node_info_batch[int_col],
            errors="ignore",
            downcast="unsigned",
        ).astype("UInt16")
    

    解决方案

    待转换列都是字符串表示的整型,使用 pd.to_numeric 转换成数值型时,因为该列有空值,所以转换成了 float 类型,而计算机存储 float 类型的数据时会有误差,如将 2.0 可能存为 1.99999999999,从而在转换成 UInt 类型时抛出上面的异常。可以在转化之前对其求近似值。如:

    # 将 int 类型的列转换成无符号整型
    for int_col in ["input_address_cnt", "addressCnt"]:
        spv_node_info_batch[int_col] = pd.to_numeric(
            spv_node_info_batch[int_col],
            errors="ignore",
        ).round(0).astype("UInt16")
    

    pd.to_numeric() :

    • 默认以字符串等形式表示则整型转换成 int64,可以通过参数 downcast="unsigned" 将其转换成 unsigned int 类型;
    • 如果是浮点数,就会转化成 float 类型。如果想将其转化成无符号整型,可以接着使用 .round().astype("UInt64");

    比较大小时要使用函数,如 eq(), le(), ge()等

    如下面的报错,services 通过 pd.to_numeric() 函数将其转换成了无符号整型 UInt64,但是 query 语句汇总使用 == 与 0 进行比较时,自动转换成了 int64,导致数据溢出而报错。如果写成 query("services.eq(0)") 就能正常执行。

    csv.Error: line contains NUL

    报错相关代码:

    with open(input_file, "r", buffering=4 << 20) as fin, open(
        output_file, "w", encoding="utf-8", buffering=4 << 20
    ) as fout:
    
        fin_reader = csv.DictReader(fin, input_file_header, delimiter="\t")
    
        # 因为输入文件中IP列的列名不一致, 只能根据列序号判断具体列名
        # file_reader 中的索引从 0 开始, 输入参数 col_idx 是从 1 开始.
        for item in fin_reader:
    

    报错分析

    待处理文件中包含了 b'\x00',以 'wb'模式打开文件,并追加 b'\x00' 便可以复现该报错。

    如果不使用 csv 模块,使用 for line in fin: 可以在 open(file_path, 'r', encoding='utf-8') 模式下正常读取文件。

    使用 csv 模块时,该模块不允许出现 \x00 这样的 NULL 字节,因此会报错。

    解决方案

    不再使用 csv 模块,使用 dict(zip()) 将 key 与 value 创建关联。其余处理步骤和之前一致。

    with open(
        input_file, "r", encoding="utf-8", buffering=4 << 20, newline=""
    ) as fin, open(
        output_file, "w", encoding="utf-8", buffering=4 << 20, newline=""
    ) as fout:
        input_file_header = [item.strip() for item in input_file_firstline.split("\t")]
    
        for line in fin:
            try:
                line = line.replace("\x00", "").replace("\0", "")
                item = dict(zip(input_file_header, line.strip().split("\t")))
    

    存入数据库时的报错

    Data too long for column user_agent

    报错原因分析

    第1,2张截图:带插入数据中的 user_agent 字段超过了表中 user_agent 字段预定义的长度,所以无法插入。

    第3张截图:addr_recv_services 的类型应该是 uint64,其中有个值是 8446744073709551615,超出了MySQL数据库中预定义的 uint的范围(uint32),所以报错,应该将 addr_recv_services 的范围改为 unsigned bigint。

    解决方案

    将表 btc_flow_version 中 user_agent 字段的长度由 32 改为 1000, 将 addr_recv_services 改为 bigint unsigned 类型。

    读取文件时的解析错误

    报错信息

    pandas.errors.ParserError: Error tokenizing data.C error: EOF inside string starting at row 29425
    

    相关代码

    version_info = pd.read_csv(
        version_info_file,
        sep="\t",
        dtype=pd.StringDtype(),
        na_values=["{}", "[]", "::", "0.0.0.0"],
        usecols=["源IP", "源IPv6", "user_agent", "services", "出现次数"],
    )
    

    报错分析

    在 user_agent 字段中有一个是以 " 开头,pandas 读取或写 csv/tsv 文件时,默认的 quotechar 是 ", 引用类型(quoting)是 QUOTE_MINIMAL, 因此会将 " 视为 quotechar,并且在该行 user_agent 字段只找到一个 ",所以抛出该错误。

    解决方式

    在 pd.read_csv() 读取文件时添加参数:quoting=csv.QUOTE_NONE, 将最前的 ' 或 " 视为字符串的一部分,而不是 quotechar。

    空值相关

    ",".join(x.unique().tolist())

    报错信息

    TypeError: sequence item 0: expected str instance, NAType found
    
    

    报错分析

    user-agent 列中包含 空值,将所有值连成字符串时,导致报错。

    解决方法

    得到唯一值列表后,应该将其中的空值去掉,再连成字符串。

    ",".join(x.unique().dropna().tolist())

    读取空文件, pandas.errors.EmptyDataError: No columns to parse from file

    当读取空文件时, 就会遇到这样的报错.

    local variable referenced before assignment

    先对要使用的变量做初始化.

    序列化与反序列化

    TypeError: unhashable type: "set"

    chainadmin/process_data/flow_stat.py

    相关代码:

    for single_file_stats in single_stats_list:
        # 将 mining_flow_stats 有的key, 而 stats 没有的key, 加入stats
        for key in single_file_stats.keys() - mining_flow_stats.keys():
            mining_flow_stats[key] = dict()
    

    报错分析: set 类型的数据不能做 dict 的 key.

    具体原因是 get_stats() 函数多进程统计时, key 值会出现 {'矿', '工', 'I', 'P'}. 导致报错.

    相关文章

      网友评论

          本文标题:数据分析工作中遇到的一些BUG,解决方案及反思(Python)

          本文链接:https://www.haomeiwen.com/subject/gaxsydtx.html