Pandas直接读取arff格式的文件

举报
小小明-代码实体 发表于 2021/10/11 23:30:08 2021/10/11
【摘要】 作者:小小明 常规arff文件读取 之前有位群友遇到了arff格式的数据,却不知道怎么读取: 然后我让这位群友把文件发我,给我分析一下,我用文件编辑器打开后,发现格式如下: 只是...

作者:小小明

常规arff文件读取

之前有位群友遇到了arff格式的数据,却不知道怎么读取:

image-20210119005646208

然后我让这位群友把文件发我,给我分析一下,我用文件编辑器打开后,发现格式如下:

image-20210119010137692

只是一个文本文本而已,解析文本文件我实在太擅长了。可以看到:

  • 编码是utf-8
  • 列名都在以@attribute开头的行
  • 数据在@data的后面的部分

理解了这三点,我马上就能用pandas直接读取它,下面看看代码:

import pandas as pd

with open("adult_census_19210979.arff", encoding="utf-8") as f:
    header = []
    for line in f:
        if line.startswith("@attribute"):
            header.append(line.split()[1])
        elif line.startswith("@data"):
            break
    df = pd.read_csv(f, header=None)
    df.columns = header
df

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

结果:

image-20210119010657950

为了后续使用方便,我们可以将上面的代码封装成函数:

def read_arrf(file):
    with open(file, encoding="utf-8") as f:
        header = []
        for line in f:
            if line.startswith("@attribute"):
                header.append(line.split()[1])
            elif line.startswith("@data"):
                break
        df = pd.read_csv(f, header=None)
        df.columns = header
    return df

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

这样,读取任何arrf文件都方便,只需要直接传入即可:

read_arrf("adult_census_19210979.arff")

  
 
  • 1

然后我得到了:

image-20210119012055657

image-20210119011024820

不过其实scipy已经含有读取这种常规的arff文件的方法:

import pandas as pd
from scipy.io import arff

data, _ = arff.loadarff("adult_census_19210979.arff")
df = pd.DataFrame(data)
df

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

image-20210323005542972

不一样的地方主要在于字符串都会读成字节的形式。

稀疏矩阵形式的arff文件读取

这只是开胃小菜,昨天有位即将从电子科技大学毕业的网友联系到我,说arff文件不仅仅只有上面的存储形式,还有以稀疏矩阵的格式存储的。

数据文件来源:http://sites.labic.icmc.usp.br/text_collections/?C=D;O=A

例如:

以稀疏矩阵形式存储时,存储格式是指定位置存对应的值(空格分割)。

最终完整的读取代码为:

import pandas as pd


def read_sparse_arrf(file):
    with open(file, encoding="utf-8") as f:
        header = []
        default_field = {}
        field_num = 0
        for line in f:
            if line.startswith("@attribute") or line.startswith("@ATTRIBUTE"):
                _, name, field_type = line.split()
                header.append(name)
                if field_type.startswith("{"):
                    default_field[field_num] = field_type[1:-1].split(",")[0]
                field_num += 1
            elif line.startswith("@data") or line.startswith("@DATA"):
                break
        default_field_keys = set(default_field.keys())
        width = len(header)
        data = []
        for line in f:
            line = line.strip()
            if not line:
                continue
            tmp = [0]*width
            flags = set()
            for kv in line[1:-1].split(","):
                k, v = kv.split()
                k = int(k)
                if k not in default_field_keys:
                    v = int(v)
                flags.add(k)
                tmp[k] = v
            for k in default_field_keys-flags:
                tmp[k] = default_field[k]
            data.append(tmp)
    return pd.DataFrame(data, columns=header)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

测试读取:

df = read_sparse_arrf("CSTR_sparse.arff")
df

  
 
  • 1
  • 2

df = read_sparse_arrf("oh15.arff")
df

  
 
  • 1
  • 2

image-20210323010711200

注意:上面代码假设了稀疏矩阵形式的arrf文件,非{}可选形式,均为数值类型。

最终这位朋友对结果还挺满意的:

image-20210323011301842

我感觉要感谢这个朋友指出我没有碰到过的这种arrf格式,所以这个红包我就不收了。

文章来源: xxmdmst.blog.csdn.net,作者:小小明-代码实体,版权归原作者所有,如需转载,请联系作者。

原文链接:xxmdmst.blog.csdn.net/article/details/112798246

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。