数据操作

六、数据操作

本章学习内容:

  • 数据导入、存储
  • 数据处理

数据操作最重要的一步也是第一步就是收集数据,而收集数据的方式有很多种,第一种就是我们已经将数据下载到了本地,在本地通过文件进行访问,第二种就是需要到网站的API处获取数据或者网页上爬取数据,还有一种可能就是你的公司里面有自己的数据库,直接访问数据库里面的数据进行分析。需要注意的是我们不仅需要将数据收集起来还要将不同格式的数据进行整理,最后再做相应的操作。

数据操作_第1张图片

1、数据导入、存储

访问数据是数据分析的所必须的第一步,只有访问到数据才可以对数据进行分析。

1.1、文本格式

常用pandas解析函数:

pandas提供了一些用于将表格型数据读取为DataFrame对象的函数。以下

函数 描述
read_csv 从文件、url或者文件型对象读取分割好的数据,逗号是默认分隔符
read_table 从文件、url或者文件型对象读取分割好的数据,制表符(’\t’)是默认分隔符
read_fwf 读取定宽格式数据(无分隔符)
read_clipboard 读取剪贴板中的数据,可以看做read_table的剪贴板。再将网页转换为表格
read_excel 从Excel的XLS或者XLSX文件中读取表格数据
read_hdf 读取pandas写的HDF5文件
read_html 从HTML文件中读取所有表格数据
read_json 从json字符串中读取数据
read_pickle 从Python pickle格式中存储的任意对象
read_msgpack 二进制格式编码的pandas数据
read_sas 读取存储于sas系统自定义存储格式的SAS数据集
read_stata 读取Stata文件格式的数据集
read_feather 读取Feather二进制文件格式
read_sql 将SQL查询的结果(SQLAlchemy)读取为pandas的DataFrame

数据操作_第2张图片

我们可以通过上表对这些解析函数有一个简单了解,其中read_csv和read_table是以后用得最多的两个方法,接下来我们主要就这两个方法测试。

(1)、read_csv
csv文件就是一个以逗号分隔字段的纯文本文件,用于测试的文件是本身是一个Excel文件,需要修改一下扩展名,但是简单的修改后缀名不行,还需要将字符编码改变为utf-8,因为默认的是ASCII,否则是会报错的。然后就可以通过read_csv将它读入到一个DataFrame:

import pandas as pd

df = pd.read_csv("E:/Test/test3.csv")
df
	name	age	sex
0	佩奇	181	乔治	19

数据操作_第3张图片

注意:

到这里可能就会有些人有疑问了,为什么我的文件路径不对啊,那是因为在我们这个方法当中的路径当它往左斜的时候需要用双斜杠,否则就要使用右斜杠

(2)、read_table

还可以使用read_table,并且指定分隔符

import pandas as pd
df = pd.read_csv("E:/Test/test3.csv")
df

name	age	sex
0	佩奇	181	乔治	19

数据操作_第4张图片

如果不指定分隔符,它的数据之间会有逗号。

以上只是简单的读取操作,

指定列名

pandas可以帮助我们自动分配列名,也可以自己指定列名
默认列名

import pandas as pd
df = pd.read_csv("E:/Test/test.csv",header=None)
df
    0	1	2	3	4	5
0	a	b	c	d	e	f
1	g	h	i	j	k	l
2	m	n	o	p	q	r

数据操作_第5张图片

指定列名

import pandas as pd
df = pd.read_csv("E:/Test/test.csv",names=['数','据','分','析','真','好','玩'])
df

数据操作_第6张图片

具体还有那些参数,通过表格展示一下,这些参数是read_csv和read_table共有的

参数 描述
path 表明文件系统位置的字符串、URL或者文件型对象
sep或delimiter 用于分隔每行字段的字符序列或正则表达式
header 用作列名的行号,默认是0(第一行),如果没有为None
names 结果的列名列表,和header=None一起用
skiprows 从文件开头起,需要跳过的行数或者行号列表
na_values 用NA替换的值序列(可以用来处理缺失值)
data_parser 用于解析日期的函数
nrows 从文件开头处读取的行数
chunksize 用于设置迭代的块大小
encoding 设置文本编码

分块读取文件

刚才我们读取文件是把整个文件都读取出来了,那接下来我们就尝试分块读取文本文件,因为不是所有的文件内容都只有这么少,我们在实际运用当中会需要读取文件的一个小片段。

读取大文件的时候可以添加一个参数使得显示的内容更加紧凑

import pandas as pd
pd.options.display.max_rows = 3
df = pd.read_csv("E:/Test/test.csv")
df

数据操作_第7张图片

还可以通过上面表格中提到的 nrows 参数选择只读取其中的几行。

1.2、二进制

pickle

在Python中有一个自带的序列化模块pickle,它是进行二进制格式操作存储数据最高效、最方便的方式之一。在pandas中有一个to_pickle方法可以将数据以pickle格式写入硬盘

import pandas as pd
df = pd.read_csv("E:/Test/test_j.csv")
df.to_pickle("E:/Test/df_pickle")

运行完之后会发现没反应,但是可以打开你存储的文件夹会发现这个pickle文件已经存到里面了。

虽然说这种方式非常方便,但是却很难保证格式的长期有效性。一个今天被pickle化的对象可能明天会因为库的新版本而无法反序列化.在pandas当中还支持其他的二进制格式。接着往下看

HDF5

HDF5主要用于存储大量的科学数组数据。以C库的形式提供,并且有许多其他语言的接口,例如:JAVA、Julia,当然还有我们的Python。HDF5中的HDF代表分层数据格式,每个HDF5文件可以存储多个数据集并且支持元数据

pandas.read_hdf函数是使用HDF5格式的一个快捷方法

import pandas as pd
import numpy as np
frame = pd.DataFrame({'a':np.random.randn(100)})

frame.to_hdf("E:/Test/mydata.h5",'obj3',format='table')
pd.read_hdf('E:/Test/mydata.h5','obj3',where=['index < 5'])

数据操作_第8张图片

数据操作_第9张图片

1.3、Web API

现在很多网站都有公开的API,通过JSON或者其他什么格式提供数据服务。那接下来,我们就通过Python的requests模块访问Web API。

import requests
import pandas as pd
url = "https://api.github.com/repos/pandas-dev/pandas/issues"
resp = requests.get(url)
data = resp.json()
# 因为data中的每个元素都是一个字典,可以直接将data传给DataFrame,并且将其中自己喜欢的字段展示出来
issues = pd.DataFrame(data,columns=['number','title','labels','state'])
issues

数据操作_第10张图片

2、数据处理

经过前面的了解,对于数据的导入以及存储已经有了一个简单的了解,但是在实际的工作情况当中,拿到的数据不可能都是预想的格式,所以说,就需要通过一些文本处理工具将这种特殊数据从一种形式转换为另一种可以接受的形式,正好在Python的pandas库当中就为我们提供了一个高级、灵活和快速的工具集,将数据转换成想要的格式。

数据操作_第11张图片

2.1、处理缺失值

缺失数据在数据分析的应用当中是很常见的,pandas的目标之一就是尽可能的无影响的处理缺失值。在pandas当中使用浮点值NaN(Not a Number来表是缺失值)。处理缺失值的最常见的两种的方法:第一个就是直接将那个值丢弃,第二种方式就是补全缺失值。

属性 描述
dropna 根据各标签的值中是否存在缺失数据对轴标签进行过滤。
fillna 用指定值或插值方法(如ffill或bfill)填充缺失数据
isnull 返回一个含有布尔值的对象,这些布尔值表示哪些值是缺失值/NA
notnull isnull的否定式

过滤缺失值

data = pd.Series(['pandas','numpy',np.nan,'matplotlib'])
-------------------------------------------
data.isnull()
运行结果:
0    False
1    False
2     True
3    False
dtype: bool    # 返回一个布尔值数组
-------------------------------------------
data[0] = None  # python中内置的None值在对象数组种也可以作为NA
data.notnull()
运行结果:
0    False
1     True
2    False
3     True
dtype: bool
-------------------------------------------
data_1 = pd.Series([1,np.nan,3,np.nan,5.5,9])
data_1.dropna()  # 丢弃任何含有缺失值的行
运行结果:
0    1.0
2    3.0
4    5.5
5    9.0
dtype: float64
# data_1[data_1.notnull()]等价于data_1.dropna()

以上都是对Series这种一维数组的缺失值处理,如果对于DataFrame这种二维数组的处理就会出现一些问题。

df = pd.DataFrame([[1,3,5,7,9],[2,4,6,np.nan],[1.5,5.,6.3,np.nan],[4.,2.3,np.nan,8,9.],[np.nan,np.nan,np.nan,np.nan,np.nan]])
df
运行结果:
    0	1	2	3	4
0	1.0	3.0	5.0	7.0	9.0
1	2.0	4.0	6.0	NaN	NaN
2	1.5	5.0	6.3	NaN	NaN
3	4.0	2.3	NaN	8.0	9.0
4	NaN	NaN	NaN	NaN	NaN
-------------------------------------------
cleaned = df.dropna()
cleaned
运行结果:
    0	1	2	3	4
0	1.0	3.0	5.0	7.0	9.0
# 所有带有缺失值的行全被丢弃了

对于这种情况可以通过传递参数来解决:

df.dropna(how="all")  # 丢弃全为缺失值的行
运行结果:
    0	1	2	3	4
0	1.0	3.0	5.0	7.0	9.0
1	2.0	4.0	6.0	NaN	NaN
2	1.5	5.0	6.3	NaN	NaN
3	4.0	2.3	NaN	8.0	9.0
-------------------------------------------
df[4] = np.nan
df.dropna(axis=1,how="all") # 丢弃全为缺失值的列
运行结果:
	0	1	2	3
0	1.0	3.0	5.0	7.0
1	2.0	4.0	6.0	NaN
2	1.5	5.0	6.3	NaN
3	4.0	2.3	NaN	8.0
4	NaN	NaN	NaN	NaN
-------------------------------------------

补全缺失值

有时候在操作数据的时候可能不想过滤掉缺失数据,因为有可能会丢弃和他有关的其他数据,而是希望通过一些其他方式来填补那些缺失的地方。fillna方法是处理这些问题最主要的方法。

df.fillna(0)  # 替换缺失值为0
运行结果:
    0	1	2	3	4
0	1.0	3.0	5.0	7.0	0.0
1	2.0	4.0	6.0	0.0	0.0
2	1.5	5.0	6.3	0.0	0.0
3	4.0	2.3	0.0	8.0	0.0
4	0.0	0.0	0.0	0.0	0.0
-------------------------------------------
df.fillna({1:0.5,2:0})  # 对不同的列填充不同的值
	0	1	2	3	4
0	1.0	3.0	5.0	7.0	NaN
1	2.0	4.0	6.0	NaN	NaN
2	1.5	5.0	6.3	NaN	NaN
3	4.0	2.3	0.0	8.0	NaN
4	NaN	0.5	0.0	NaN	NaN
-------------------------------------------
_ = df.fillna(0,inplace=True)
df
运行结果:
	0	1	2	3	4
0	1.0	3.0	5.0	7.0	0.0
1	2.0	4.0	6.0	0.0	0.0
2	1.5	5.0	6.3	0.0	0.0
3	4.0	2.3	0.0	8.0	0.0
4	0.0	0.0	0.0	0.0	0.0

使用fillna还可以进行插值

df1 = pd.DataFrame(np.random.randn(6,3))
df1
运行结果:
    0	        1	        2
0	0.475304	-1.274166	1.467016
1	-0.113910	0.935197	-1.008954
2	0.218006	0.209405	0.224217
3	1.878587	0.492774	-1.391237
4	-0.702284	0.863064	0.939069
5	-1.450531	0.994467	0.265843
# 一组数据数
-------------------------------------------
df1.iloc[2:,1] = np.nan  # 将第二列第三行以后的数据都转换为缺失值
df1.iloc[4:,2] = np.nan  # 将第三列第五行以后的数据都转换为缺失值
运行结果:
	0	        1	        2
0	1.073202	0.644249	-0.089127
1	-0.028500	0.479373	-0.271212
2	1.575710	NaN	        -0.119795
3	-0.202480	NaN	        0.385250
4	-1.090317	NaN	        NaN
5	0.985767	NaN	        NaN
-------------------------------------------
df1.fillna(method='ffill')
运行结果:
    0	        1	        2
0	1.073202	0.644249	-0.089127
1	-0.028500	0.479373	-0.271212
2	1.575710	0.479373	-0.119795
3	-0.202480	0.479373	0.385250
4	-1.090317	0.479373	0.385250
5	0.985767	0.479373	0.385250
# 参数limit还可以设置替换的行
参数 说明
value 用于填充缺失值的标量值或字典对象
method 插值方式。如果函数调用时未指定其他参数的话,默认为"ffill"
axis 待填充的轴,默认axis=0
inplace 修改调用者对象而不产生副本
limit 可以连续填充的最大数量

数据操作_第12张图片

2.2、数据转换

1、删除重复值

data = pd.DataFrame({"k1":['one','two'] * 3 + ['two'],
                    "k2":[1,1,2,3,3,4,4]})
data
运行结果:
    k1	k2
0	one	1
1	two	1
2	one	2
3	two	3
4	one	3
5	two	4
6	two	4
-----------------------------------------------
data.duplicated()  # 返回一个布尔型Series,表示各行是否是重复行
0    False
1    False
2    False
3    False
4    False
5    False
6     True
dtype: bool
-----------------------------------------------
data.drop_duplicates()  # 返回一个DataFrame,重复的数组会标为False
	k1	k2
0	one	1
1	two	1
2	one	2
3	two	3
4	one	3
5	two	4   
# 重复的行被删除了
-----------------------------------------------

以上方法是针对全部列,还可以通过传入参数对部分指定列进行重复项判断。

data['v1'] = range(7)  # 添加一个v1列
data.drop_duplicates(['k1','k2'])  # 可以传入一个列表,指定列,默认保留第一个出现的值组合
    k1	k2	v1
0	one	1	0
1	two	1	1
2	one	2	2
3	two	3	3
4	one	3	4
5	two	4	5
-----------------------------------------------
data.drop_duplicates(['k1','k2'],keep='last')  # 默认保留最后一个出现的值组合
	k1	k2	v1
0	one	1	0
1	two	1	1
2	one	2	2
3	two	3	3
4	one	3	4
6	two	4	6

2、使用函数或映射进行数据转换

data = pd.DataFrame({"goods":['Iphone','HUAWEI','SAMSUNG','MI','OPPO'], "price":[6000,4000,5000,3000,3000]})
data
运行结果:
	goods	price
0	Iphone	6000
1	HUAWEI	4000
2	SAMSUNG	5000
3	MI	    3000
4	OPPO	3000

现在有这样一组数据,假设现在需要加上一列数据。将每样商品的出产国家加上

# 先定义一个不同商品到产地的映射
produce_nation = {
    "iphone":'America',
    "huawei":'China',
    "samsung":'Korea',
    "mi":'China',
    "oppo":'China'
}
# 因为定义的商品全是大写,需要全部转换为小写
lower_cased = data['goods'].str.lower()

# 通过map映射添加一列出产国家数据
data['nation'] =  lower_cased.map(produce_nation)
运行结果:
	goods	price	nation
0	Iphone	6000	America
1	HUAWEI	4000	China
2	SAMSUNG	5000	Korea
3	MI	    3000	China
4	OPPO	3000	China

也可以通过一个函数完成这些工作:

data['goods'].map(lambda x:produce_nation[x.lower()])
运行结果:
0    America
1      China
2      Korea
3      China
4      China
Name: goods, dtype: object

3、替换值

利用fillna()方法填充缺失数据是值替换的一种特殊情况。接下来可以使用replace方法进行替换值操作。

data = pd.Series([1., -999., 2., -999., -1000., 3.])
data   # 生成一个Series数组
运行结果:
0       1.0
1    -999.0
2       2.0
3    -999.0
4   -1000.0
5       3.0
dtype: float64
----------------------------------------------
# 其中-999可能是缺失值的某一标识,需要使用NA替代这些值
1、
data.replace(-999, np.nan)  # 通过replace产生一个新的Series,除非传入inplace=True
运行结果:
0       1.0
1       NaN
2       2.0
3       NaN
4   -1000.0
5       3.0
dtype: float64
2、
data.replace([-999, -1000], np.nan)  # 一次性替换多个值
3、
data.replace([-999, -1000], [np.nan, 0])  # 替换不同的值,通过列表
4、
data.replace({-999: np.nan, -1000: 0})  # 替换不同的值,通过字典

数据操作_第13张图片

你可能感兴趣的:(数据分析)