288 Pandas 读取 URL 路径的文件
数据输入路径,可以是文件路径,也可以是 URL,或者实现 read 方法的任意对象。
如下经典的数据集 iris,直接通过 URL 获取。
In [160]: pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data')
Out[160]:
5.1 3.5 1.4 0.2 Iris-setosa
0 4.9 3.0 1.4 0.2 Iris-setosa
1 4.7 3.2 1.3 0.2 Iris-setosa
2 4.6 3.1 1.5 0.2 Iris-setosa
3 5.0 3.6 1.4 0.2 Iris-setosa
4 5.4 3.9 1.7 0.4 Iris-setosa
.. ... ... ... ... ...
144 6.7 3.0 5.2 2.3 Iris-virginica
145 6.3 2.5 5.0 1.9 Iris-virginica
146 6.5 3.0 5.2 2.0 Iris-virginica
147 6.2 3.4 5.4 2.3 Iris-virginica
148 5.9 3.0 5.1 1.8 Iris-virginica
[149 rows x 5 columns]
289 Pandas 读取文件之 sep 分隔符
默认为逗号,注意:如果分割字符长度大于1,且不是 \s+
, 启动 Python 引擎解析。
举例:test.csv 文件分割符为 \t,
如果使用 sep 默认的逗号分隔符,读入后的数据混为一体。
# 创建并保存数据
In [1]: d = {'id':[1,2],'name':['gz','lh'],'age':[10,12]}
In [2]: df = pd.DataFrame(d)
In [3]: df.to_csv('test.csv',sep='\t')
#读取数据
In [4]: df = pd.read_csv('test.csv')
In [5]: df
Out[5]:
\tid\tname\tage
0 0\t1\tgz\t10
1 1\t2\tlh\t12
sep 必须设置为 '\t'
,数据分割才会正常。
In [6]: df = pd.read_csv('test.csv',sep='\t')
In [6]: df
Out[6]:
Unnamed: 0 id name age
0 0 1 gz 10
1 1 2 lh 12
290 Pandas 读取之列选择属性
参数用于选取数据文件的哪些列到 DataFrame 中,如下所示,只想使用源数据文件的 id 和 age 两列,那么可以为 usecols 参数赋值为 ['id','name']:
In [1]: df = pd.read_csv('test.csv',delim_whitespace=True,usecols=['id','name'])
In [2]: df
Out[2]:
id name
0 1 gz
1 2 lh
291 Pandas 读取之空值处理
参数可以配置哪些值需要处理成Na/NaN, 类型为字典,键指明哪一列,值为看做 Na/NaN 的字符。
假设我们的数据文件如下,date 列中有一个 #
值,我们想把它处理成 NaN 值。
In [1]: d = {'id':[1,2],'name':['gz','lh'],'age':[10,12],'date':['2020-03-10','#']}
In [2]: df = pd.DataFrame(d)
In [3]: df.to_csv('test_date.csv',sep=' ',index=False)
In [4]: df = pd.read_csv('test_date.csv',sep='\s+')
可以使用,na_values 实现:
In [37]: df = pd.read_csv('test_date.csv',sep='\s+',na_values=['#'])
In [38]: df
Out[38]:
id name age date
0 1 gz 10 2020-03-10
1 2 lh 12 NaN
keepdefaultna 是和 navalues 搭配的,如果前者为 True,则 navalues 被解析为 Na/NaN 的字符除了用户设置外,还包括默认值。
292 Pandas 之分块读入数据
iterator 取值 boolean, 默认为 False, 返回一个 TextFileReader 对象,以便逐块处理文件。
这个在文件很大时,内存无法容纳所有数据文件,此时分批读入,依次处理。
具体操作演示如下,我们的文件数据域一共有 2 行。
先读入一行,get_chunk 设置为 1 表示一次读入一行
In [64]: chunk = pd.read_csv('test.csv',sep='\s+',iterator=True)
In [65]: chunk.get_chunk(1)
Out[65]:
id name age
0 1 gz 10
再读入下一行,
In [66]: chunk.get_chunk(1)
Out[66]:
id name age
1 2 lh 12
此时已到文件末尾,再次读入会报异常,
In [108]: chunk.get_chunk(1)
StopIteration
293 Pandas 之随机选取一部分数据案例
对于动辄就几十或几百个 G 的数据,在读取的这么大数据的时候,我们有没有办法随机选取一小部分数据,然后读入内存,快速了解数据和开展 EDA ?
使用 Pandas 的 skiprows 和 概率知识,就能做到。
下面解释具体怎么做。
如下所示,读取某 100 G 大小的 big_data.csv 数据
1) 使用 skiprows 参数,
2) x > 0 确保首行读入,
3) np.random.rand() > 0.01 表示 99% 的数据都会被随机过滤掉
言外之意,只有全部数据的 1% 才有机会选入内存中。
import pandas as pd
import numpy as np
df = pd.read_csv("big_data.csv",
skiprows =
lambda x: x>0 and np.random.rand() > 0.01)
print("The shape of the df is {}.
It has been reduced 100 times!".format(df.shape))
使用这种方法,读取的数据量迅速缩减到原来的 1% ,对于迅速展开数据分析有一定的帮助。
294 Pandas 之一维数组 Series
Series 是 pandas 两大数据结构中(DataFrame,Series) 的一种,先从 Series 的定义说起,Series 是一种类似于一维数组的对象,它由一组数据域以及一组与之相关联的数据标签和索引组成。
Series 对象也是一个 NumPy 的数组,因此 NumPy 的数组处理函数可以直接对 Series 进行处理。
与此同时,Series 除了可以使用位置索引作为下标存取元素之外,还可以使用标签下标
存取元素,这一点和字典相似,每个 Series 对象都由两个数组组成:
- index:它是从 NumPy 数组继承的 Index 对象,保存标签信息。
- values:保存值的 NumPy 数组。
接下来,分别介绍 Series 内元素的增加、删除、修改、访问。
295 Pandas 之创建 Series
Series 的标准构造函数, 列举常用的几个参数:
Series(data=None, index=None, dtype=None, name=None)
其中,data 为数据部分,index 为标签部分,省略下默认为自增整数索引,dtype 为 str, numpy.dtype, or ExtensionDtype。
创建一个 series,如下:
In [85]: ps = pd.Series(data=[-3,2,1],index=['a','f','b'],dtype=np.float32)
In [86]: ps
Out[86]:
a -3.0
f 2.0
b 1.0
dtype: float32
296 Series 之增加元素
在 ps 基础上增加一个元素,使用 append,如下:
In [112]: ps.append(pd.Series(data=[-8.0],index=['f']))
Out[112]:
a 4.0
f 2.0
b 1.0
f -8.0
dtype: float64
可以看到,Pandas 允许包含重复的标签
In [114]: psn = ps.append(pd.Series(data=[-8.0],index=['f']))
In [115]: psn
Out[115]:
a 4.0
f 2.0
b 1.0
f -8.0
dtype: float64
In [116]: psn['f']
Out[116]:
f 2.0
f -8.0
dtype: float64
利用标签访问元素,返回所有带标签的数据。
297 Series之删除元素
使用 drop 删除指定标签的数据,如下:
In [119]: ps
Out[119]:
a 4.0
f 2.0
b 1.0
dtype: float32
In [120]: psd = ps.drop('f')
In [121]: psd
Out[121]:
a 4.0
b 1.0
dtype: float32
注意不管是 append 操作,还是 drop 操作,都是发生在原数据的副本上,不是原数据上。
298 Series 之修改元素
通过标签修改对应数据,如下所示:
In [123]: psn
Out[123]:
a 4.0
f 2.0
b 1.0
f -8.0
dtype: float64
In [124]: psn['f'] = 10.0
In [125]: psn
Out[125]:
a 4.0
f 10.0
b 1.0
f 10.0
dtype: float64
标签相同的数据,都会被修改。
299 Series 之访问元素
访问元素,Pandas 提供两种方法,
- 一种通过默认的整数索引,在 Series 对象未被显示的指定 label 时,都是通过索引访问;
- 另一种方式是通过标签访问。
In [126]: ps
Out[126]:
a 4.0
f 2.0
b 1.0
dtype: float32
In [128]: ps[2] # 索引访问
Out[128]: 1.0
In [127]: ps['b'] # 标签访问
Out[127]: 1.0
300 Pandas 之二维数组 DataFrame
DataFrame, Pandas 两个重要数据结构中的另一个,可以看做是 Series 的容器。
DataFrame 同时具有行、列标签,是二维的数组,行方向轴 axis 为 0, 列方向 axis 为 1,如下:
axis : {0 or 'index', 1 or 'columns'}
创建 DataFrame
DataFrame 构造函数如下:
DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
参数意义与 Series 相似,不再赘述。
创建 DataFrame 的常用方法:
In [134]: df = pd.DataFrame([['gz',4.0,'2019-01-01'],['lg',1.2,'2019-06-01']],index = ['a','f'], columns = ['nm', 'y','da'])
In [135]: df
Out[135]:
nm y da
a gz 4.0 2019-01-01
f lg 1.2 2019-06-01
也可以通过字典传入,得到一样的 DataFrame,如下:
In [136]: df2 = pd.DataFrame({'nm':['gz','lg'],'y':[4.0,1.2], 'da':['2019-01-01', '2019-06-01']},index = ['a','f'])
In [137]: df2
Out[137]:
nm y da
a gz 4.0 2019-01-01
f lg 1.2 2019-06-01
301 DataFrame 之增加数据
通过增加一个 Series,扩充到 DataFrame 中,如下所示:
In [143]: dfn = df.append(pd.Series(data=['zx',3.6,'2019-05-01'],index=['nm','y','da'],name='b'))
In [144]: dfn
Out[144]:
nm y da
a gz 4.0 2019-01-01
f lg 1.2 2019-06-01
b zx 3.6 2019-05-01
Series 的 index 与 DataFrame 的 column 对齐,name 与 DataFrame 的 index 对齐。
302 DataFrame 之删除数据
与 Series 删除类似,也是使用 drop 删除指定索引或标签的数据。如下,注意删除仍然是在 dfn 的副本上进行,像下面这样删除对 dfn 没有任何影响。
In [145]: dfn.drop('b')
Out[145]:
nm y da
a gz 4.0 2019-01-01
f lg 1.2 2019-06-01
如果要删除某列,需要设定 axis 为 1, 如下所示:
In [147]: dfn.drop('y',axis=1)
Out[147]:
nm da
a gz 2019-01-01
f lg 2019-06-01
b zx 2019-05-01
303 DataFrame 之修改数据
修改依然是先通过索引或标签定位到数据,然后修改,如下所示:
In [151]: dfn.loc['a','da']='2019-04-01'
In [152]: dfn
Out[1