Pandas IO操作详解

数据分析过程中经常需要进行读写操作,Pandas实现了很多 IO 操作的API,这里简单做了一个列举。

更多:Pandas

格式类型数据描述ReaderWriter
textCSVread_csvto_csv
textJSONread_jsonto_json
textHTMLread_htmlto_html
textclipboardread_clipboardto_clipboard
binaryExcelread_excelto_excel
binaryHDF5read_hdfto_hdf
binaryFeatherread_featherto_feather
binaryMsgpackread_msgpackto_msgpack
binaryStataread_statato_stata
binarySASread_sas
binaryPython Pickleread_pickleto_pickle
SQLSQLread_sqlto_sql
SQLGoogle Big Queryread_gbqto_gbq

可以看到,Pandas 的 I/O API是像 pd.read_csv() 一样访问的一组顶级 reader 函数,相应的 writer 函数是像 df.to_csv() 那样访问的对象方法。

这里我们介绍几个常用的API。

# 导入相关库
import numpy as np
import pandas as pd
from io import StringIO

read_csv

读取 csv 文件算是一种最常见的操作了。假如已经有人将一些用户的信息记录在了一个csv文件中,我们如何通过 Pandas 读取呢?

读取之前先来看下这个文件里的内容吧。

!cat ../data/user_info.csv
name,age,birth,sex
Tom,18.0,2000-02-10,
Bob,30.0,1988-10-17,male

可以看到,一共有 4 列,分别是 nameagebirthsex 。我们可以直接使用 pd.read_csv 来读取。

pd.read_csv("../data/user_info.csv")

nameagebirthsex
0Tom18.02000-02-10NaN
1Bob30.01988-10-17male

可以看到,读取出来生成了一个 DataFrame,索引是自动创建的一个数字,我们可以设置参数 index_col 来将某列设置为索引,可以传入索引号或者名称。

pd.read_csv("../data/user_info.csv", index_col="name")

agebirthsex
name


Tom18.02000-02-10NaN
Bob30.01988-10-17male

除了可以从文件中读取,我们还可以从 StringIO 对象中读取。

data="name,age,birth,sexnTom,18.0,2000-02-10,nBob,30.0,1988-10-17,male"
print(data)
name,age,birth,sex
Tom,18.0,2000-02-10,
Bob,30.0,1988-10-17,male
pd.read_csv(StringIO(data))

nameagebirthsex
0Tom18.02000-02-10NaN
1Bob30.01988-10-17male

当然了,你还可以设置参数 sep 来自定义字段之间的分隔符,设置参数 lineterminator 来自定义每行的分隔符。

data = "name|age|birth|sex~Tom|18.0|2000-02-10|~Bob|30.0|1988-10-17|male"

pd.read_csv(StringIO(data), sep="|", lineterminator="~")

nameagebirthsex
0Tom18.02000-02-10NaN
1Bob30.01988-10-17male

在读取时,解析器会进行类型推断,任何非数字列都会以对象dtype的形式出现。当然我们也可以自己指定数据类型。

pd.read_csv(StringIO(data), sep="|", lineterminator="~", dtype={"age": int})

nameagebirthsex
0Tom182000-02-10NaN
1Bob301988-10-17male

Pandas 默认将第一行作为标题,但是有时候,csv文件并没有标题,我们可以设置参数 names 来添加标题。

data="Tom,18.0,2000-02-10,nBob,30.0,1988-10-17,male"
print(data)
Tom,18.0,2000-02-10,
Bob,30.0,1988-10-17,male
pd.read_csv(StringIO(data), names=["name", "age", "birth", "sex"])

nameagebirthsex
0Tom18.02000-02-10NaN
1Bob30.01988-10-17male

有时候可能只需要读取部分列的数据,可以指定参数 user_cols

data="name,age,birth,sexnTom,18.0,2000-02-10,nBob,30.0,1988-10-17,male"
print(data)
name,age,birth,sex
Tom,18.0,2000-02-10,
Bob,30.0,1988-10-17,male
pd.read_csv(StringIO(data), usecols=["name", "age"])

nameage
0Tom18.0
1Bob30.0

关于缺失值的处理,也是有技巧的。默认参数 keep_default_na=False,会将空值都填充为 NaN。

pd.read_csv(StringIO(data))

nameagebirthsex
0Tom18.02000-02-10NaN
1Bob30.01988-10-17male
pd.read_csv(StringIO(data), keep_default_na=False)

nameagebirthsex
0Tom18.02000-02-10
1Bob30.01988-10-17male

有时候,空值的定义比较广泛,假定我们认为 18 也是空值,那么将它加入到参数 na_values 中即可。

pd.read_csv(StringIO(data), na_values=[18])

nameagebirthsex
0TomNaN2000-02-10NaN
1Bob30.01988-10-17male

了解了 pd.read_csv 如何使用之后,to_csv 就非常方便了,这里就不做介绍了。

to_json

通常在得到了 DataFrame 之后,有时候我们需要将它转为一个 json 字符串,可以使用 to_json 来完成。

转换时,可以通过指定参数 orient 来输出不同格式的格式,之后以下几个参数:



split字典像索引 – > [索引],列 – > [列],数据 – > [值]}
records列表像{[列 – >值},…,{列 – >值}]
index字典像{索引 – > {列 – >值}}
columns字典像{列 – > {索引 – >值}}
values只是值数组

DataFrame 默认情况下使用 columns 这种形式,Series 默认情况下使用 index 这种形式。

设置为 columns 后会将数据作为嵌套JSON对象进行序列化,并将列标签作为主索引。

df = pd.read_csv("../data/user_info.csv", index_col="name")
df

agebirthsex
name


Tom18.02000-02-10NaN
Bob30.01988-10-17male
print(df.to_json())
{"age":{"Tom":18.0,"Bob":30.0},"birth":{"Tom":"2000-02-10","Bob":"1988-10-17"},"sex":{"Tom":null,"Bob":"male"}}

设置为index 后会将数据作为嵌套JSON对象进行序列化,并将索引标签作为主索引。

print(df.to_json(orient="index"))
{"Tom":{"age":18.0,"birth":"2000-02-10","sex":null},"Bob":{"age":30.0,"birth":"1988-10-17","sex":"male"}}

设置为 records 后会将数据序列化为列 – >值记录的JSON数组,不包括索引标签。

print(df.to_json(orient="records"))
[{"age":18.0,"birth":"2000-02-10","sex":null},{"age":30.0,"birth":"1988-10-17","sex":"male"}]

设置为 values 后会将是一个仅用于嵌套JSON数组值,不包含列和索引标签。

print(df.to_json(orient="values"))
[[18.0,"2000-02-10",null],[30.0,"1988-10-17","male"]]

设置为 split 后会将序列化为包含值,索引和列的单独条目的JSON对象。

print(df.to_json(orient="split"))
{"columns":["age","birth","sex"],"index":["Tom","Bob"],"data":[[18.0,"2000-02-10",null],[30.0,"1988-10-17","male"]]}

对于 read_json,这些参数也是同样的道理。

发表评论

电子邮件地址不会被公开。 必填项已用*标注