数据加载、存储与文件格式(python)


访问数据是使用本书所介绍的这些工具的第一步。我会着重介绍 pandas 的数据输入与输出,虽然别的库中也有不少以此为目的的工具。

输入输出通常可以划分为几个大类:读取文本文件和其他更高效的磁盘存储格式,加载数据库中的数据,利用 Web API 操作网络资源

6.1 读写文本格式的数据

pandas 提供了一些用于将表格型数据读取为DataFrame对象的函数。表 6-1 对它们进行了总结,其中read_csv和read_table可能会是你今后用得最多的。
在这里插入图片描述
我将大致介绍一下这些函数在将文本数据转换为DataFrame时所用到的一些技术。这些函数的选项可以划分为以下几个大类:

索引:将一个或多个列当做返回的DataFrame处理,以及是否从文件、用户获取列名。
类型推断和数据转换:包括用户定义值的转换、和自定义的缺失值标记列表等。
日期解析:包括组合功能,比如将分散在多个列中的日期时间信息组合成结果中的单个列。
迭代:支持对大文件进行逐块迭代。
不规整数据问题:跳过一些行、页脚、注释或其他一些不重要的东西(比如由成千上万个逗号隔开的数值数据)。

因为工作中实际碰到的数据可能十分混乱,一些数据加载函数(尤其是read_csv)的选项逐渐变得复杂起来。面对不同的参数,感到头痛很正常(read_csv有超过 50 个参数)。pandas 文档有这些参数的例子,如果你感到阅读某个文件很难,可以通过相似的足够多的例子找到正确的参数。
其中一些函数,比如pandas.read_csv,有类型推断功能,因为列数据的类型不属于数据类型。也就是说,你不需要指定列的类型到底是数值、整数、布尔值,还是字符串。其它的数据格式,如 HDF5、Feather 和 msgpack,会在格式中存储数据类型。

日期和其他自定义类型的处理需要多花点工夫才行。首先我们来看一个以逗号分隔的(CSV)文本文件:

In [8]: !cat examples/ex1.csv
a,b,c,d,message
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo

笔记:这里,我用的是 Unix 的cat shell 命令将文件的原始内容打印到屏幕上。如果你用的是 Windows,你可以使用type达到同样的效果

由于该文件以逗号分隔,所以我们可以使用read_csv将其读入一个DataFrame:

In [9]: df = pd.read_csv('examples/ex1.csv')

In [10]: df
Out[10]: 
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

我们还可以使用read_table(从文件,URL,文件型对象中加载带有分隔符的数据,默认分隔符为制表符(\t)),并指定分割符。
注意:read_table可以提取的对象类型是一样的,只是默认分隔符read_csv是逗号,read_table是制表符。
csv对象的分隔符是逗号,所以使用read_table读取csv文件时,需要指定分割符为逗号,而不是用默认分隔符

In [11]: pd.read_table('examples/ex1.csv', sep=',')
Out[11]: 
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

#如果不指定分隔符的话,默认分隔符是制表符,与scv文件的分隔符不一致结果会这样
只有一列,所有的数据都放在一列里面了
In [11]: pd.read_table('examples/ex1.csv', sep=',')
Out[11]: 
	a,b,c,d,message
0	1,2,3,4,hello
1	5,6,7,8,word
2	9,10,11,12,foo

如果读取的文件没有标题行(列名)
需要使用关键字header指定首行不是标题行(header=None)(默认为header=‘infer’,默认首行是标题行,所以如果不特别指定,首行会读取为列名)
或者使用关键字names指定列名(指定情况下首行就默认不是列名了)

#在不指定关键字header的情况下,默认首行就是标题行
In [13]: pd.read_csv('examples/ex2.csv')
Out[13]: 
	1	2	3	4	hello
0	5	6	7	8	word
1	9	10	11	12	foo

#指定首行非标题行
In [13]: pd.read_csv('examples/ex2.csv', header=None)
Out[13]: 
   0   1   2   3      4
0  1   2   3   4  hello
1  5   6   7   8  world
2  9  10  11  12    foo
#指定列名的情况下,不把首行默认为标题行
In [14]: pd.read_csv('examples/ex2.csv', names=['a', 'b', 'c', 'd', 'message'])
Out[14]: 
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

如果你想要指定某列作为索引,可以使用关键字index_col

In [15]: names = ['a', 'b', 'c', 'd', 'message']

In [16]: pd.read_csv('examples/ex2.csv', names=names, index_col='message')
Out[16]: 
         a   b   c   d
message               
hello    1   2   3   4
world    5   6   7   8
foo      9  10  11  12

如果你想把多个列指定为索引(做一个层次化的索引)只需要使用关键字index_col,以列表的形式指定多列

In [17]: !cat examples/csv_mindex.csv
key1,key2,value1,value2
one,a,1,2
one,b,3,4
one,c,5,6
one,d,7,8
two,a,9,10
two,b,11,12
two,c,13,14
two,d,15,16

In [18]: parsed = pd.read_csv('examples/csv_mindex.csv',
   ....:                      index_col=['key1', 'key2'])

In [19]: parsed
Out[19]: 
           value1  value2
key1 key2                
one  a          1       2
     b          3       4
     c          5       6
     d          7       8
two  a          9      10
     b         11      12
     c         13      14
     d         15      16

有些情况下,有些表格可能不是用固定的分隔符去分隔字段的(比如空白符或其它模式)。看看下面这个文本文件:

In [20]: list(open('examples/ex3.txt'))
Out[20]: 
['            A         B         C\n',
 'aaa -0.264438 -1.026059 -0.619500\n',
 'bbb  0.927272  0.302904 -0.032399\n',
 'ccc -0.264273 -0.386314 -0.217601\n',
 'ddd -0.871858 -0.348382  1.100491\n']

虽然可以手动对数据进行规整,这里的字段是被数量不同的空白字符间隔开的。这种情况下,你可以传递一个正则表达式作为read_table的分隔符。可以用正则表达式表达为\s+,于是有:

In [21]: result = pd.read_table('examples/ex3.txt', sep='\s+')

In [22]: result
Out[22]: 
            A         B         C
aaa -0.264438 -1.026059 -0.619500
bbb  0.927272  0.302904 -0.032399
ccc -0.264273 -0.386314 -0.217601
ddd -0.871858 -0.348382  1.100491

这里,由于列名比数据行的数量少,所以read_table推断第一列应该是DataFrame的索引。

In [23]: !cat examples/ex4.csv
# hey!
a,b,c,d,message
# just wanted to make things more difficult for you
# who reads CSV files with computers, anyway?
1,2,3,4,hello
5,6,7,8,world
9,10,11,12,foo
In [24]: pd.read_csv('examples/ex4.csv', skiprows=[0, 2, 3])
Out[24]: 
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

缺失值处理是文件解析任务中的一个重要组成部分。缺失数据经常是要么没有(空字符串),要么用某个标记值表示。默认情况下,pandas 会用一组经常出现的标记值进行识别,比如 NA 及NULL

In [25]: !cat examples/ex5.csv
something,a,b,c,d,message
one,1,2,3,4,NA
two,5,6,,8,world
three,9,10,11,12,foo
In [26]: result = pd.read_csv('examples/ex5.csv')

In [27]: result
Out[27]: 
  something  a   b     c   d message
0       one  1   2   3.0   4     NaN
1       two  5   6   NaN   8   world
2     three  9  10  11.0  12     foo

In [28]: pd.isnull(result)
Out[28]: 
   something      a      b      c      d  message
0      False  False  False  False  False     True
1      False  False  False   True  False    False
2      False  False  False  False  False    False

na_values可以用一个列表或集合的字符串表示缺失值:(此关键字是用来指定什么是缺失值的,比如可以指定字符串hello为缺失值,这样读取的时候hello就会是别为缺失值)

In [29]: result = pd.read_csv('examples/ex5.csv', na_values=['NULL'])

In [30]: result
Out[30]: 
  something  a   b     c   d message
0       one  1   2   3.0   4     NaN
1       two  5   6   NaN   8   world
2     three  9  10  11.0  12     foo

还可以通过字典的形式,针对各列指定不同的缺失值

In [31]: sentinels = {'message': ['foo', 'NA'], 'something': ['two']}

In [32]: pd.read_csv('examples/ex5.csv', na_values=sentinels)
Out[32]:
something  a   b     c   d message
0       one  1   2   3.0   4     NaN
1       NaN  5   6   NaN   8   world
2     three  9  10  11.0  12     NaN

表 6-2 列出了pandas.read_csv和pandas.read_table常用的选项。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

逐块读取文本文件

在处理很大的文件时,或找出大文件中的参数集以便于后续处理时,你可能只想读取文件的一小部分或逐块对文件进行迭代。

在看大文件之前,我们先设置 pandas 显示地更紧些:

#设置大文件只显示10行
In [33]: pd.options.display.max_rows = 10

然后有:

In [34]: result = pd.read_csv('examples/ex6.csv')

In [35]: result
Out[35]: 
           one       two     three      four key
0     0.467976 -0.038649 -0.295344 -1.824726   L
1    -0.358893  1.404453  0.704965 -0.200638   B
2    -0.501840  0.659254 -0.421691 -0.057688   G
3     0.204886  1.074134  1.388361 -0.982404   R
4     0.354628 -0.133116  0.283763 -0.837063   Q
...        ...       ...       ...       ...  ..
9995  2.311896 -0.417070 -1.409599 -0.515821   L
9996 -0.479893 -0.650419  0.745152 -0.646038   E
9997  0.523331  0.787112  0.486066  1.093156   K
9998 -0.362559  0.598894 -1.843201  0.887292   G
9999 -0.096376 -1.012999 -0.657431 -0.573315   0
[10000 rows x 5 columns]
If you want to only read a small

如果只想读取几行,可以通过nrows来指定需要读取的行数

In [36]: pd.read_csv('examples/ex6.csv', nrows=5)
Out[36]: 
        one       two     three      four key
0  0.467976 -0.038649 -0.295344 -1.824726   L
1 -0.358893  1.404453  0.704965 -0.200638   B
2 -0.501840  0.659254 -0.421691 -0.057688   G
3  0.204886  1.074134  1.388361 -0.982404   R
4  0.354628 -0.133116  0.283763 -0.837063   Q

要逐块读取文件,可以指定chunksize(行数):

In [874]: chunker = pd.read_csv('ch06/ex6.csv', chunksize=1000)

In [875]: chunker
Out[875]: <pandas.io.parsers.TextParser at 0x8398150>

read_csv所返回的这个TextParser对象使你可以根据chunksize对文件进行逐块迭代。比如说,我们可以迭代处理ex6.csv,将值计数聚合到"key"列中,如下所示:

chunker = pd.read_csv('examples/ex6.csv', chunksize=1000)

tot = pd.Series([])
for piece in chunker:
    tot = tot.add(piece['key'].value_counts(), fill_value=0)

tot = tot.sort_values(ascending=False)

然后有:

In [40]: tot[:10]
Out[40]: 
E    368.0
X    364.0
L    346.0
O    343.0
Q    340.0
M    338.0
J    337.0
F    335.0
K    334.0
H    330.0
dtype: float64

TextParser还有一个get_chunk方法,它使你可以读取任意大小的块。

将数据写出到文本格式

数据也可以被输出为分隔符格式的文本。我们再来看看之前读过的一个 CSV 文件:

In [41]: data = pd.read_csv('examples/ex5.csv')

In [42]: data
Out[42]: 
  something  a   b     c   d message
0       one  1   2   3.0   4     NaN
1       two  5   6   NaN   8   world
2     three  9  10  11.0  12     foo

利用DataFrame的to_csv方法,我们可以将数据写到一个以逗号分隔的文件中:

In [43]: data.to_csv('examples/out.csv')

In [44]: !cat examples/out.csv
,something,a,b,c,d,message
0,one,1,2,3.0,4,
1,two,5,6,,8,world
2,three,9,10,11.0,12,foo

当然,还可以使用其他分隔符(由于这里直接写出到sys.stdout,所以仅仅是打印出文本结果而已):

In [45]: import sys

In [46]: data.to_csv(sys.stdout, sep='|')
|something|a|b|c|d|message
0|one|1|2|3.0|4|
1|two|5|6||8|world
2|three|9|10|11.0|12|foo

对于缺失值,在输出结果中显示为空值,也可以通过na_rep关键字指定为特定的标记值

In [47]: data.to_csv(sys.stdout, na_rep='NULL')
,something,a,b,c,d,message
0,one,1,2,3.0,4,NULL
1,two,5,6,NULL,8,world
2,three,9,10,11.0,12,foo

对于行和列,默认是会写出行和列的标签的。也可以通过index和header来指定是否写出

#通过index=False, header=False禁用行和列
In [48]: data.to_csv(sys.stdout, index=False, header=False)
one,1,2,3.0,4,
two,5,6,,8,world
three,9,10,11.0,12,foo

还可以只写出一部分列,并以指定的顺序排列

In [49]: data.to_csv(sys.stdout, index=False, columns=['a', 'b', 'c'])
a,b,c
1,2,3.0
5,6,
9,10,11.0

Series也有一个to_csv方法:

In [50]: dates = pd.date_range('1/1/2000', periods=7)

In [51]: ts = pd.Series(np.arange(7), index=dates)

In [52]: ts.to_csv('examples/tseries.csv')

In [53]: !cat examples/tseries.csv
2000-01-01,0
2000-01-02,1
2000-01-03,2
2000-01-04,3
2000-01-05,4
2000-01-06,5
2000-01-07,6

JSON 数据

JSON(JavaScript Object Notation 的简称)已经成为通过 HTTP 请求在 Web 浏览器和其他应用程序之间发送数据的标准格式之一。它是一种比表格型文本格式(如 CSV)灵活得多的数据格式。下面是一个例子:

obj = """
{"name": "Wes",
 "places_lived": ["United States", "Spain", "Germany"],
 "pet": null,
 "siblings": [{"name": "Scott", "age": 30, "pets": ["Zeus", "Zuko"]},
              {"name": "Katie", "age": 38,
               "pets": ["Sixes", "Stache", "Cisco"]}]
}
"""

除其空值null和一些其他的细微差别(如列表末尾不允许存在多余的逗号)之外,JSON 非常接近于有效的 Python 代码。基本类型有对象(字典)、数组(列表)、字符串、数值、布尔值以及null。对象中所有的键都必须是字符串。许多 Python 库都可以读写 JSON 数据。我将使用json,因为它是构建于 Python 标准库中的。通过json.loads即可将 JSON 字符串转换成 Python 形式:
函数json.loads可以将JSON字符串转换成Python

In [62]: import json

In [63]: result = json.loads(obj)

In [64]: result
Out[64]: 
{'name': 'Wes',
 'pet': None,
 'places_lived': ['United States', 'Spain', 'Germany'],
 'siblings': [{'age': 30, 'name': 'Scott', 'pets': ['Zeus', 'Zuko']},
  {'age': 38, 'name': 'Katie', 'pets': ['Sixes', 'Stache', 'Cisco']}]}

json.dumps则将 Python 对象转换成 JSON 格式:

In [65]: asjson = json.dumps(result)

如何将(一个或一组)JSON 对象转换为DataFrame或其他便于分析的数据结构就由你决定了。最简单方便的方式是:向DataFrame构造器传入一个字典的列表(就是原先的 JSON 对象),并选取数据字段的子集:
这里仅仅是把字段转换为DataFrame格式,且指定只获取name,age列

In [66]: siblings = pd.DataFrame(result['siblings'], columns=['name', 'age'])

In [67]: siblings
Out[67]: 
    name  age
0  Scott   30
1  Katie   38

pandas.read_json可以自动将特别格式的 JSON 数据集转换为Series或DataFrame。例如:

In [68]: !cat examples/example.json
[{"a": 1, "b": 2, "c": 3},
 {"a": 4, "b": 5, "c": 6},
 {"a": 7, "b": 8, "c": 9}]

pandas.read_json的默认选项假设 JSON 数组中的每个对象是表格中的一行:

In [69]: data = pd.read_json('examples/example.json')

In [70]: data
Out[70]: 
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9

如果你需要将数据从 pandas 输出到 JSON,可以使用to_json方法:

In [71]: print(data.to_json())
{"a":{"0":1,"1":4,"2":7},"b":{"0":2,"1":5,"2":8},"c":{"0":3,"1":6,"2":9}}

In [72]: print(data.to_json(orient='records'))
[{"a":1,"b":2,"c":3},{"a":4,"b":5,"c":6},{"a":7,"b":8,"c":9}]

注意后面还有一些其他的文件格式的读取,但是比较复杂,讲的又比较乱就不写了,之后有更好的讲解内容,再进行补充

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Jupyter Notebook是一个非常强大的数据分析工具,可以实现数据加载储存和文件结构管理。本文将简单介绍如何使用Jupyter Notebook进行数据加载储存和文件结构管理。 数据加载储存 Jupyter Notebook 支持多种数据格式的读写,包括CSV、Excel、JSON、SQL、HDF5等。以下是一些基本的数据读写操作: 1. CSV 文件读写 使用 pandas 库中的 read_csv 函数可以读取 CSV 文件,并使用 to_csv 函数可以将 DataFrame 对象保存为 CSV 文件。 ```python import pandas as pd # 读取 CSV 文件 df = pd.read_csv('data.csv') # 将 DataFrame 对象保存为 CSV 文件 df.to_csv('data_new.csv') ``` 2. Excel 文件读写 使用 pandas 库中的 read_excel 函数可以读取 Excel 文件,并使用 to_excel 函数可以将 DataFrame 对象保存为 Excel 文件。 ```python import pandas as pd # 读取 Excel 文件 df = pd.read_excel('data.xlsx') # 将 DataFrame 对象保存为 Excel 文件 df.to_excel('data_new.xlsx') ``` 3. JSON 文件读写 使用 pandas 库中的 read_json 函数可以读取 JSON 文件,并使用 to_json 函数可以将 DataFrame 对象保存为 JSON 文件。 ```python import pandas as pd # 读取 JSON 文件 df = pd.read_json('data.json') # 将 DataFrame 对象保存为 JSON 文件 df.to_json('data_new.json') ``` 4. SQL 数据库读写 使用 pandas 库中的 read_sql 函数可以读取 SQL 数据库中的数据,并使用 to_sql 函数可以将 DataFrame 对象保存到 SQL 数据库中。 ```python import pandas as pd import sqlite3 # 连接 SQLite 数据库 conn = sqlite3.connect('data.db') # 读取 SQL 数据库中的数据 df = pd.read_sql('SELECT * FROM data_table', conn) # 将 DataFrame 对象保存到 SQL 数据库中 df.to_sql('data_table_new', conn) ``` 5. HDF5 文件读写 使用 pandas 库中的 read_hdf 函数可以读取 HDF5 文件,并使用 to_hdf 函数可以将 DataFrame 对象保存为 HDF5 文件。 ```python import pandas as pd # 读取 HDF5 文件 df = pd.read_hdf('data.h5') # 将 DataFrame 对象保存为 HDF5 文件 df.to_hdf('data_new.h5', key='data') ``` 文件结构管理 Jupyter Notebook 支持文件结构管理,并支持文件夹和文件的创建、删除和重命名操作。使用 Jupyter Notebook 的文件结构管理功能,可以更好地组织和管理数据分析项目的文件和文件夹。 1. 文件夹和文件的创建 在 Jupyter Notebook 的文件浏览器中,可以通过点击 New Folder 或者 New 文件按钮来创建新的文件夹或者文件。 2. 文件夹和文件的删除 在 Jupyter Notebook 的文件浏览器中,可以通过选中要删除的文件夹或者文件,然后点击 Delete 按钮来删除它们。 3. 文件夹和文件的重命名 在 Jupyter Notebook 的文件浏览器中,可以通过选中要重命名的文件夹或者文件,然后点击 Rename 按钮来重命名它们。 总结 本文介绍了如何使用 Jupyter Notebook 进行数据加载储存和文件结构管理。数据加载储存方面,Jupyter Notebook 支持多种数据格式的读写,包括 CSV、Excel、JSON、SQL、HDF5 等;文件结构管理方面,Jupyter Notebook 支持文件夹和文件的创建、删除和重命名操作,可以更好地组织和管理数据分析项目的文件和文件夹。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值