pandas
Pandas是线上服务类型,数据分析和数据处理(在机器学习中数据处理)
数据分析三剑客:
numpy数值计算
pandas数据分析
matplotlib+seaborn数据可视化
pandas中有两组数据类型,一个是Series,另一个是DataFrame。
importpandasaspd
1、 Series
Series是一种类似与一维数组的对象,由下面两个部分组成:
values:一组数据(ndarray类型)
key:相关的数据索引标签
可理解为带索引的一维数组。
1.1 Series属性
index—— 索引项
values——索引值,numpy.ndarray类型
1.2 创建Series
1.2.1 通过已有数据创建
指定内容,默认索引
pd.Series(np.arange(5))
#输出
00
11
22
33
44
指定索引:通过设置index参数指定索引
pd.Series([10,12,23,45,23],index=['a','b','c','d','e'])
#输出
a10
b12
c23
d45
e23
dtype: int64
1.2.2 通过字典创建
pd.Series({'a':3,'b':4,'c':5})
#输出
a3
b4
c5
dtype: int64
name参数
pd.Series(data=[1,2,3,4],index=list('abcd'),name='demo')
#输出
a1
b2
c3
d4
Name: demo, dtype: int64
copy属性:类似于Python中的deepcopy
arr= np.array([1,2,3,4,5])
ser= pd.Series(data=arr)
##这样当我们修改arr中数据时,ser中的数据也会跟着改变
ser= pd.Series(data=arr,copy=True)
##此时再修改arr中的数据时,ser中的数据不会再改变。
1.3 Series的索引和切片
可以使用中括号取单个索引(此时返回的是元素类型),
或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。
分为显示索引和隐式索引:
1.3.1 常规索引的方式
s= pd.Series({'a':3,'b':4,'c':5})
s['a':'b'],s[:1],s.c
#输出
a3
b4
dtype: int64
###############
a3
dtype: int64
###############
5
!!!注意!!!利用自定义的index和自带索引切片时的范围闭合问题哦!
这里先介绍:
索引的类型有两种:
枚举型索引:特征索引是连续数值
关联型索引:特征索引都是离散字符类型
1.3.2 显式索引
使用index中的关联类型作为索引值
使用.loc[](推荐)
可以理解为pandas是ndarray的升级版,但是Series也可是dict的升级版
注意,此时是闭区间
s.loc['a':'c'],s['a':'c']
#输出
b4
c5
dtype: int64,
a3
b4
c5
dtype: int64
1.3.3 隐式索引
使用整数作为索引值
使用.iloc[](推荐)
注意,此时是半闭区间
s.iloc[:1]
#输出
a3
dtype: int64
自然而然切片也有常规切片、显式切片和隐式切片
#常规
s[1:-1]
s['a':'d']
#显式
s.loc['a':'c']
#隐式
s.iloc[0:-1]
1.4 Series的基本概念
可以把Series看成一个定长的有序字典
可以通过ndim,shape,size,index,values等得到series的属性
ser.index获得索引
ser.values获得值
ser.keys() 获得索引
可以通过head(),tail()快速查看Series对象的样式
共同都有一个参数n,默认值为5
S= pd.Series(data=np.random.randint(0,10,10000))
#Linux 当中 head -n xxx.txt 读取前几行
S.head(n=3)
#输出
04
19
28
dtype: int32
当索引没有对应的值时,可能出现缺失数据显示NaN的情况。
||
可以使用pd.isnull(),pd.notnull(),或自带isnull(),notnull()函数检测缺失数据。
S=pd.Series([None,1,2,3])
#mysql where demo is not null
index= S.notnull()
index
#输出
0False
1 True
2 True
3 True
dtype: bool
2、DataFrame
DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。
行索引:index
列索引:columns
值:values(numpy的二维数组)
我们的 训练集(一些二维的数据)都是二维的,那么Series满足不了这个条件,xy轴,轴上的一点(0,0)。
2.1 DataFrame的创建
2.2 DataFrame的属性和方法
pd.DataFrame(array, index,columns)
因为pandas是集成了numpy的,属性方面用法和功能都类似
属性:
shape(形状)
values(除去行列索引后的值)
T(行列转置)
index(行索引)
columns(列索引)
方法:
head(size)——显示前size行数据,默认前五行
tail(size)——显示后size行数据,默认后五行
2.3 设置索引
修改行列索引值
只能整体修改,不能修改单独某一项
重设索引
reset_index(drop=False)
#重置索引值,默认drop为False,不删除原索引,将其单独立为一列,在此基础上将索引重置
设置新的索引 `set_index(keys, drop=True)`
keys:列索引名称或者列索引名称的列表;
drop: boolean,默认为True,当做新的索引,删除原来的列
#设置多个索引
df= pd.DataFrame({'month':[1,4,7,10],'year':[2012,2014,2013,2016],'sale':[55,40,84,31]})
df.set_index(['month'])
df.set_index(['year','month']) #此设置可以同时设置多层次索引如['year','month'],设置之后此时返回的index是MultiIndex类型
2.4 MultiIndex
多级或分层索引对象,可用于存放三维数据
index属性
names:levels的名称
levels:每个level的元组值
new_df = df.set_index(['year', 'month'])
new_df.index.names
##输出
FrozenList(['year', 'month'])
new_df.index.levels
#输出
FrozenList([[2012, 2013, 2014, 2016], [1, 4, 7, 10]])
索引的堆(stack)
stack() 把列索引转变为行索引
unstack() 把行索引转变为列索引
2.5 DataFrame的索引
2.5.1 对列进行索引
通过类似字典的方式
通过属性的方式
可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。
DataFrame的中括号,只能获取列索引。
2.5.2 对行进行索引
使用.loc[]加index来进行行索引
使用.iloc[]加整数来进行行索引
data = pd.DataFrame({'A':[12,23,67,89],'B':[67,76,45,89],'c':[90,89,45,78]},index=['语文','数学','英语','自然'])
data
#输出
A B c
语文 12 67 90
数学 23 76 89
英语 67 45 45
自然 89 89 78
data.loc['语文']
#输出
A 12
B 67
c 90
Name: 语文, dtype: int64
data.iloc[0]
#输出
A 12
B 67
c 90
Name: 语文, dtype: int64
2.5.3 对元素索引的方法
使用列索引
使用行索引(iloc[3,1]相当于两个参数;iloc[[3,3]] 里面的[3,3]看做一个参数)
使用values属性(二维numpy数组)
data.iloc[0,1] #相当于第0行的第二个元素
data.iloc[[0,0]] #可以同时选取多行数据,这里就是选取两次第0行的数据
#输出
A B c
语文 12 67 90
语文 12 67 90
使用行索引loc切片和使用隐式iloc思维方式和二维array一致,故意不写清楚,如果已经忘记,正好一起把二维array切片回顾一下吧!
2.6 数据的增删改查CURD操作
2.6.1 插入
2.6.1 .1 增加一行
data.loc['政治']=[67,38,95]
#
A B c
语文 12 67 90
数学 23 76 89
英语 67 45 45
自然 89 89 78
政治 67 38 95
2.6.1.2 增加一列
在增加时,增加一列 一列中有多少个元素是不知道的
data.loc[:,'D']=np.nan
data
#输出
A B c D
语文 12 67 90 NaN
数学 23 76 89 NaN
英语 67 45 45 NaN
自然 89 89 78 NaN
政治 67 38 95 NaN
2.6.2 修改
欲修改先查询
col_index = data.A == 67
col_index
#输出匹配结果是布尔值类型
语文 False
数学 False
英语 True
自然 False
政治 True
Name: A, dtype: bool
根据查询到的index结果再去修改
#因为匹配结果有两个,而只想修改第二个
res = data[col_index].iloc[1]
res.D = 90
#被拷贝的新数据,在单独的内存空间中,把修改好的数据覆盖
data.loc[col_index].iloc[1]=res
另外一种方法,常用点:
new_data = user.query("username=='李晶'")
new_data.age = 50
user.loc[new_data.index] = new_data
user
#输出
username sex addr seet age
东 70 77 81 40 NaN
南 89 5 8 32 NaN
西 60 37 72 18 NaN
北 78 17 54 44 NaN
中 8 62 84 55 NaN
东邪 李晶 ? 红浪漫 1123 50.0
2.6.3 查
见上
2.6.4 删除
labels参数代表要被删除的索引名称
axis=0参数代表是删除行还是列
inplace 发生变化的数据把原数据替换
#删除列
user.drop(labels='age',axis=1,inplace=True)
#删除行
user.drop(labels='东邪',axis=0,inplace=True)
2.7 丢失数据的处理
在python中有两种
np.nan
None
pandas 中对于空的操作
isnull():#把每一列中True和False求和以便统计缺失数据数目
notnull()
dropna() #过滤空值 :
删除行还是列:
在数据分析中我们删除行
在探索性数据分析中,如果行缺失的比较多那就删除行,如果列缺失的比较多那就删除列
fillna() 不好玩,代码想写自己联系吧
填充空值
1.指定填充
2.前后填充,不能使用value=None
2.8 聚合操作
【注意】
需要指定axis
【小技巧】和unstack()相反,聚合的时候,axis等于哪一个,哪一个就保留。
所谓的聚合操作:平均数,标准方差,最大值,最小值……
首先你要理解各个函数的数学和统计学意义哦!就很容易了!
3 、pandas的拼接操作
pandas主要作用就是对数据进行一个统计 pandas 也有类似于 left join 的操作 、select union select(联合查询)。
相当于Mysql中的联表查询,联合查询 的操作:pd.concat(), pd.append() pd.merge()
3.1 使用Pandas连接MySQL获取数据
importpymysql
fromsqlalchemyimportcreate_engine
conn= create_engine("mysql+pymysql://root:Chenjiajian1225@wst.life:3306/py1907?charset=utf8")
sql1= "select * from usr_info;"
demo= pd.read_sql(sql1,conn)
demo.head()
#输出
idnamegenderpassword
01tommale123456
12bobmale123456
23lucyfemale123456
34lilyfemale123456
45alexmale123456
uid= demo.query("gender == 'female'").id
uid= uid.tolist()
uid= tuple(uid)
sql2= f"select * from usr_info where id in {uid};"
female_info= pd.read_sql(sql2,conn)
female_info
#输出
idnamegenderpassword
03lucyfemale123456
14lilyfemale123456
29evafemale123456
310ellafemale123456
# 数据的操作就是DataFrame数据类型的操作
3.2 使用pd.concat()级联
pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,keys=None, levels=None, names=None, verify_integrity=False,copy=True)
3.2.1 简单级联
和np.concatenate一样,优先增加行数(默认axis=0)
pd.concat([demo,female_info],join='outer')
#输出
idnamegenderpassword
01tommale123456
12bobmale123456
23lucyfemale123456
34lilyfemale123456
45alexmale123456
56johnmale123456
67jackmale123456
78tomasmale123456
89evafemale123456
910ellafemale123456
1011nickmale123456
03lucyfemale123456
14lilyfemale123456
29evafemale123456
310ellafemale123456
####看到没,index可以重复。
pd.concat((demo,female_info),axis=1,join='outer')
#输出
idnamegenderpasswordidnamegenderpassword
01tommale1234563.0lucyfemale123456
12bobmale1234564.0lilyfemale123456
23lucyfemale1234569.0evafemale123456
34lilyfemale12345610.0ellafemale123456
45alexmale123456NaNNaNNaNNaN
56johnmale123456NaNNaNNaNNaN
67jackmale123456NaNNaNNaNNaN
78tomasmale123456NaNNaNNaNNaN
89evafemale123456NaNNaNNaNNaN
910ellafemale123456NaNNaNNaNNaN
1011nickmale123456NaNNaNNaNNaN
可以通过设置axis来改变级联方向
注意index在级联时可以重复
也可以选择忽略ignore_index,重新索引
或者使用多层索引 keys
3.2.2 不匹配级联
不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
有2种连接方式:
外连接:补NaN(默认模式)outer
内连接:只连接匹配的项 inner
使用concat()模拟联合查询
(select* fromuser_info limit10) union(selectuserid,orderid,paidtime fromorder_info limit10) ;
要求联合查询的字段数量要相同
数据类型可以不相同
两边的字段名称可以不相同
字段名称显示问题以左边的表为基准
那在pandas中,是不是得先让用于union的数据符合条件,即抽提出要用于联合查询的数据列,把列名称修改成一致的,之后联合在一起。
3.2.3 使用append()函数添加
由于在后面级联的使用非常普遍,因此有一个函数append专门用于在后面添加,append 和 concat 相似,默认也是上下拼接。
user_info.append(union_right,ignore_index=True)
3.3 使用pd.merge()合并
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
on : label or list.Column or index level names to join on. These must be found in both DataFrames.
merge与concat的区别在于:
merge需要依据某一共同的行或列来进行合并
使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
默认也是内连接:how : {'left', 'right', 'outer', 'inner'}, default 'inner'。
inner 内连接,两边的关联字段对等则返回,否则过滤
left 左外连接,以左表中的关联字段为主,如果右边中的字段不匹配,则填补Null
right 右外连接,以右表中的关联字段为主,如果左边中的字段不匹配,则填补Null
outer 全外连接,如果两边的数据不对等,则两边全部填补Null
注意每一列元素的顺序不要求一致
将id设置为行号
set_index()
data.set_index(keys='userid',inplace=True)
重新设置行索引
data.reset_index(inplace=True)
指定关联列
left_on=None
right_on=None
使用left_on和right_on指定左右两边的列作为key,当左右两边的key都不相同时使用
关联列是行索引
user_info.set_index('uid',inplace=True)
order_info.set_index('userid',inplace=True)
pd.merge(user_info,order_info,left_index=True,right_index=True,how='outer')
内合并与外合并
内合并:只保留两者都有的key(默认模式)
外合并 how='outer':补NaN
左合并、右合并:how='left',how='right',
列冲突的解决
当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
可以使用suffixes=自己指定后缀
出现这种状况的场景:两张表的字段有大部分是相同的,那你让merge怎么办,它咋知道用哪一列的数据进行连接呢?
使用suffixes=自己指定后缀,就像是给同名的俩人起别称进行标识一样的。
pd.merge(user_info,union_right,left_on='uid',right_on='uid',suffixes=('_user', '_union'),how='outer')
4、数据合并的案例
4.1 为什么取得的数据不能直接用,为什么要进行数据预处理呢?
那你做菜可不得洗菜、切菜哦,准备葱姜蒜等配料呢。同样我们在拿到数据时,是不能直接用的,要‘因材处理’!
掌握数据组成和结构:表与表之间的关系,表头字段的合法性。。。。
根据表之间的关系合并数据:注意保证数据完整性用外连接,当然,要根据实际要求灵活处理。
合并数据后缺失值的查找、处理。
以上处理完也要记得最后检查下是否还存在影响数据完整性的缺失值的检查。
4.2 操作实例
第一步:
abb= pd.read_csv('../Lesson_3/state-abbrevs.csv')
abb.head()
pop= pd.read_csv('../Lesson_3/state-population.csv')
pop.head()
area= pd.read_csv('../Lesson_3/state-areas.csv')
area.head()
cols= pop.columns.tolist()
cols[0] = 'state_region'
pop.columns= cols
pop.head()
第二步:
##两表合并
abb_pop=pd.merge(abb,pop,left_on='abbreviation',right_on='state_region',how='outer')
##检查缺失值
abb_pop.isnull().sum()
##删除冗余数据列
abb_pop.drop(labels='abbreviation',axis=1,inplace=True)
abb_pop.isnull().sum()
第三步:
#缺失值的填补
indexs=abb_pop.state.isnull()
filter_data=abb_pop.loc[indexs]
filter_data.state_region.unique()
pr_inds= abb_pop.query("state_region=='PR'").index
reple= abb_pop.loc[pr_inds]
reple['state'] = 'Puerto Rico'
abb_pop.loc[pr_inds]=reple
abb_pop.isnull().sum()
usa_inds= abb_pop.query("state_region=='USA'").index
reple_usa= abb_pop.loc[usa_inds]
reple_usa['state'] = 'USA'
abb_pop.loc[usa_inds] = reple_usa
abb_pop.isnull().sum()
第四步:
#合并第三张表
cols= area.columns.tolist()
cols[1] = 'area'
area.columns= cols
abb_pop_area= pd.merge(abb_pop,area,how='outer')
abb_pop_area.head()
abb_pop_area.isnull().sum()
第五步:
#缺失值检查填补
ins=abb_pop_area.area.isnull()
area_fill= abb_pop_area.loc[ins]
state_name= [xforxinabb_pop_area.state.unique() ifx!='USA']
total_area= 0
forxinstate_name:
total_area= total_area+abb_pop_area.query(f"state=='{x}'").iloc[0].area
area_fill= abb_pop_area.loc[ins]
area_fill.area= total_area
abb_pop_area.loc[ins] =area_fill
abb_pop_area.loc[ins]
abb_pop_area.isnull().sum()
至此,数据预处理完成。
数据简单分析
---分析某一州各个年份成年与未成年分的比例
Alabama = abb_pop_area.query("state=='Alabama'")
u_pop=Alabama.query("ages =='under18'").population
t_pop = Alabama.query("ages =='total'").population
year = Alabama.year.unique()
a_pop = np.array(t_pop) - np.array(u_pop)
u_rate =np.divide(np.array(u_pop),np.array(t_pop))
a_rate = np.divide(a_pop,np.array(t_pop))
result = pd.DataFrame(np.c_[u_rate,a_rate],columns=['u_rate','a_rate'],index=year)
from matplotlib import pyplot as plt
#堆叠图()
result.plot(kind='barh',stacked=True,figsize=(10,10))
pandas数据处理
1、删除重复数据
使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True。
使用drop_duplicates()函数删除重复的行。
data.drop_duplicates(inplace=True)
2、映射
映射的含义:创建一个映射关系列表,把values元素和一个特定的标签或者字符串 绑定。
需要使用字典:
map = {
'label1':'value1',
'label2':'value2',
...
}
包含三种操作:
replace()函数:替换元素
最重要:map()函数:新建一列,修改一列
rename()函数:替换行索引
``.loc[]`` isprimarilylabelbased, butmayalsobeusedwithabooleanarray.
2.1 使用replace()函数,对values进行替换操作
还经常用来替换NaN元素,当然替换是双向的,也可以把值替换成控制,
如果想修改原来的数组,记得加上inplace=True
p1= {'math':[90,89,78,90,89],'chinese':[90,89,67,89,80],'english':[90,89,90,90,90]}
p= pd.DataFrame(data=p1)
p.loc[2:4,'english'] = np.nan
p.english.iloc[-1]='?'
#输出
mathchineseenglish
090 9090.0
189 8989.0
278 67NaN
390 89NaN
489 80?
填补空值可以用fillna()函数但是它的功能比较单一
p.fillna(value=0)
#输出
mathchinese
090 9090
189 8989
278 670
390 890
489 80?
#你看‘?’可没办法被填补,这个时候replace()就有用啦!
p.replace('?','不可知',inplace=True),
mathchineseenglish
0909090
1898989
27867NaN
39089NaN
48980不可知
p.replace(to_replace=None, value=None, inplace=False, limit=None, regex=False, method='pad')
Docstring:
Replacevaluesgivenin`to_replace` with`value`.
to_replace: str, regex, list, dict, Series, int, float, orNone
Howtofindthevaluesthatwillbereplaced.
#1、直接写由啥替换成啥
s= pd.Series([0, 1, 2, 3, 4])
s.replace(0, 5)#将0替换成5
05
11
22
33
44
========================================
df= pd.DataFrame({'A': [0, 1, 2, 3, 4],
...'B': [5, 6, 7, 8, 9],
...'C': ['a', 'b', 'c', 'd', 'e']})
df.replace(0, 5)
ABC
055a
116b
227c
338d
449e
#2、将好多元素同时替换
df.replace([0, 1, 2, 3], 4)
ABC
045a
146b
247c
348d
449e
df.replace([0, 1, 2, 3], [4, 3, 2, 1])
ABC
045a
136b
227c
318d
449e
s.replace([1, 2], method='bfill')
00
13
23
33
44
#3、字典形式的多个元素替换
df.replace({0: 10, 1: 100})
ABC
0 105a
11006b
227c
338d
449e
指定位置的替换
df.replace({'A': 0, 'B': 5}, 100)
ABC
0100100a
116b
227c
338d
449e
df.replace({'A': {0: 100, 4: 400}})
ABC
01005a
116b
227c
338d
44009e
当然也支持正则匹配替换,但是好麻烦,估计不会用哦。
2.2 rename()函数:替换索引
p.index=['a','b','c','d','e']
p.rename({'a':'A'})
#输出
mathchineseenglish
A909090
b898989
c7867NaN
d9089NaN
e8980不可知
函数参数详解:就看看好了,不是很好玩,掌握一种替换方式就行了。
df= pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
>>>df.rename(index=str, columns={"A": "a", "B": "c"})
ac
014
125
236
>>>df.rename(index=str, columns={"A": "a", "C": "c"})
aB
014
125
236
Usingaxis-styleparameters
>>>df.rename(str.lower, axis='columns')
ab
014
125
236
>>>df.rename({1: 2, 2: 4}, axis='index')
AB
014
225
436
reindex()
pandas中的reindex方法可以为series和dataframe添加或者删除索引。方法:serise.reindex()、dataframe.reindex()如果新添加的索引没有对应的值,则默认为nan。如果减少索引,就相当于一个切片操作。
# series reindex
s1= Series([1, 2, 3, 4], index=['A', 'B', 'C', 'D'])
print(s1)
'''
A 1
B 2
C 3
D 4
dtype: int64
'''
# 重新指定 index, 多出来的index,可以使用fill_value 填充
print(s1.reindex(index=['A', 'B', 'C', 'D', 'E'], fill_value= 10))
'''
A 1
B 2
C 3
D 4
E 10
dtype: int64
'''
s2= Series(['A', 'B', 'C'], index= [1, 5, 10])
print(s2)
'''
1 A
5 B
10 C
dtype: object
'''
# 修改索引,
# 将s2的索引增加到15个
# 如果新增加的索引值不存在,默认为 Nan
print(s2.reindex(index=range(15)))
'''
0 NaN
1 A
2 NaN
3 NaN
4 NaN
5 B
6 NaN
7 NaN
8 NaN
9 NaN
10 C
11 NaN
12 NaN
13 NaN
14 NaN
dtype: object
'''
# ffill : foreaward fill 向前填充,
# 如果新增加索引的值不存在,那么按照前一个非nan的值填充进去
print(s2.reindex(index=range(15), method='ffill'))
'''
0 NaN
1 A
2 A
3 A
4 A
5 B
6 B
7 B
8 B
9 B
10 C
11 C
12 C
13 C
14 C
dtype: object
'''
# reindex dataframe
df1= DataFrame(np.random.rand(25).reshape([5, 5]), index=['A', 'B', 'D', 'E', 'F'], columns=['c1', 'c2', 'c3', 'c4', 'c5'])
print(df1)
'''
c1 c2 c3 c4 c5
A 0.700437 0.844187 0.676514 0.727858 0.951458
B 0.012703 0.413588 0.048813 0.099929 0.508066
D 0.200248 0.744154 0.192892 0.700845 0.293228
E 0.774479 0.005109 0.112858 0.110954 0.247668
F 0.023236 0.727321 0.340035 0.197503 0.909180
'''
# 为 dataframe 添加一个新的索引
# 可以看到 自动 扩充为 nan
print(df1.reindex(index=['A', 'B', 'C', 'D', 'E', 'F']))
''' 自动填充为 nan
c1 c2 c3 c4 c5
A 0.700437 0.844187 0.676514 0.727858 0.951458
B 0.012703 0.413588 0.048813 0.099929 0.508066
C NaN NaN NaN NaN NaN
D 0.200248 0.744154 0.192892 0.700845 0.293228
E 0.774479 0.005109 0.112858 0.110954 0.247668
F 0.023236 0.727321 0.340035 0.197503 0.909180
'''
# 扩充列, 也是一样的
print(df1.reindex(columns=['c1', 'c2', 'c3', 'c4', 'c5', 'c6']))
'''
c1 c2 c3 c4 c5 c6
A 0.700437 0.844187 0.676514 0.727858 0.951458 NaN
B 0.012703 0.413588 0.048813 0.099929 0.508066 NaN
D 0.200248 0.744154 0.192892 0.700845 0.293228 NaN
E 0.774479 0.005109 0.112858 0.110954 0.247668 NaN
F 0.023236 0.727321 0.340035 0.197503 0.909180 NaN
'''
# 减小 index
print(s1.reindex(['A', 'B']))
''' 相当于一个切割效果
A 1
B 2
dtype: int64
'''
print(df1.reindex(index=['A', 'B']))
''' 同样是一个切片的效果
c1 c2 c3 c4 c5
A 0.601977 0.619927 0.251234 0.305101 0.491200
B 0.244261 0.734863 0.569936 0.889996 0.017936
'''
# 对于一个 serie 来说,可以使用 drop,来丢掉某些 index
print(s1.drop('A'))
''' 就只剩下 三个了
B 2
C 3
D 4
dtype: int64
'''
# dataframe drop(A) 直接去掉一行
print(df1.drop('A', axis=0))
''' axis 默认 是 行
c1 c2 c3 c4 c5
B 0.571883 0.254364 0.530883 0.295224 0.352663
D 0.858452 0.379495 0.593284 0.786078 0.949718
E 0.556276 0.643187 0.808664 0.289422 0.501041
F 0.737993 0.286072 0.332714 0.873371 0.421615
'''
print(df1.drop('c1', axis=1))
''' 将 c1 的列 去掉
c2 c3 c4 c5
A 0.326681 0.247832 0.601982 0.145905
B 0.373961 0.393819 0.439284 0.926706
D 0.558490 0.617851 0.461280 0.373102
E 0.030434 0.566498 0.383103 0.739243
F 0.982220 0.989826 0.957863 0.411514
'''
2.3 map()函数:新建一列
使用map()函数,由已有的列生成一个新列
适合处理某一单独的列,支持Series类型
注意:map函数的参数支持function和dict
function在定义的时候,必须要写一个形参,形参会代表一列中每一个元素(map函数会自动遍历)。
#映射修改
data= pd.read_excel('销售记录.xlsx')
demo= data.copy()
#把下单的日期只提取月份
defget_m(item):
returnstr(item).split()[0].split('-')[1]
#demo是一个dataframe
demo.loc[:,'下单日期'] = demo.loc[:,'下单日期'].map(get_m)
#映射类型替换
#昨天绘制散布图出现了一个问题,鸢尾花数据的类别值是str类型,散布图不支持
#.astype('category').cat.codes
importseabornassns
iris= sns.load_dataset('iris')
#['setosa', 'versicolor', 'virginica'] => [0,1,2]
iris.species.unique()
#1.字典替换方式 {'setosa':0, 'versicolor':1, 'virginica':2} 比较固定
#加入类别的数量是动态的
#2.使用函数自动识别
#设置全局变量,获取当前的类别数量
cls= iris.species.unique()
defstr2num(item):
foriinnp.arange(cls.shape[0]):
ifitem== cls[i]:
returni
iris['lables']=iris.species.map(str2num)
iris
sepal_lengthsepal_widthpetal_lengthpetal_widthspecieslables
05.13.51.40.2setosa0
14.93.01.40.2setosa0
24.73.21.30.2setosa0
34.63.11.50.2setosa0
45.03.61.40.2setosa0
55.43.91.70.4setosa0
64.63.41.40.3setosa0
2.4 transform()、apply()、agg()
map()类似值只能是一个function
3、异常值检测
使用describe()函数查看每一列的描述性统计量
iris.iloc[:,:-1].describe()
#输出各列数据的基本状况
sepal_lengthsepal_widthpetal_lengthpetal_width
count150.000000150.000000150.000000150.000000
mean5.8433333.0573333.7580001.199333
std0.8280660.4358661.7652980.762238
min4.3000002.0000001.0000000.100000
25%5.1000002.8000001.6000000.300000
50%5.8000003.0000004.3500001.300000
75%6.4000003.3000005.1000001.800000
max7.9000004.4000006.9000002.500000
pandas中.isnull().any()含义
python pandas判断缺失值一般采用 isnull(),然而生成的却是所有数据的true/false矩阵,对于庞大的数据dataframe,很难一眼看出来哪个数据缺失,一共有多少个缺失数据,缺失数据的位置。
importpandasaspd
importnumpyasnp
df= pd.DataFrame(np.random.randn(10,6))
# Make a few areas have NaN values
df.iloc[1:3,1] = np.nan
df.iloc[5,3] = np.nan
df.iloc[7:9,5] = np.nan
##输出
0 1 2 3 4 5
00.5201130.8840001.260966-0.2365970.312972-0.196281
1-0.837552 NaN0.1430170.8623550.3465500.842952
2-0.452595 NaN-0.4207900.4562151.2034590.527425
30.317503-0.9170421.780938-1.5841020.4327450.389797
4-0.7228521.704820-0.113821-1.4664580.0830020.011722
5-0.622851-0.251935-1.498837 NaN1.0983230.273814
60.3295850.075312-0.690209-3.8079240.489317-0.841368
7-1.123433-1.1874961.868894-2.046456-0.949718 NaN
81.133880-0.1104470.050385-1.1583870.188222 NaN
9-0.5137411.1962590.7045370.982395-0.585040-1.693810
df.isnull()会产生如下结果:
012345
0FalseFalseFalseFalseFalseFalse
1False TrueFalseFalseFalseFalse
2False TrueFalseFalseFalseFalse
3FalseFalseFalseFalseFalseFalse
4FalseFalseFalseFalseFalseFalse
5FalseFalseFalse TrueFalseFalse
6FalseFalseFalseFalseFalseFalse
7FalseFalseFalseFalseFalse True
8FalseFalseFalseFalseFalse True
9FalseFalseFalseFalseFalseFalse
df.isnull().any()则会判断哪些”列”存在缺失值
0False
1 True
2False
3 True
4False
5 True
dtype: bool
对于该问题,可以采用如下方式解决:
df[df.isnull().values==True] 当然也可像老师做,得到所有的index是否含有空值的结果再提取。
0 1 2 3 4 5
11.090872 NaN-0.287612-0.239234-0.5898971.849413
2-1.384721 NaN-0.1582930.011798-0.564906-0.607121
5-0.477590-2.6962390.312837 NaN0.404196-0.797050
70.369665-0.268898-0.344523-0.0944360.214753 NaN
8-0.114483-0.8423220.164269-0.812866-0.601757 NaN
####可以只显示存在缺失值的行列,清楚的确定缺失值的位置。
4、排序
sort_values() sort_index()
#根据行索引排序
data.sort_index(ascending=False) #ascending:升序
#order by 列
data.sort_values(by=['销售代表ID','数量']).iloc[:10]
5、数据聚合【重点】
5.1
数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。
数据分类处理:
分组:先把数据分为几组
用函数处理:为不同组的数据应用不同的函数以转换数据
合并:把不同组得到的结果合并起来
数据分类处理的核心: groupby()函数
groupby()在pandas中也担任分组的重担
如果想使用color列索引,计算price1的均值,可以先获取到price1列,然后再调用groupby函数,用参数指定color这一列
使用.groups属性查看各行的分组情况:
pd.DataFrame(data.groupby(by='客户省份').金额.sum())
# select avg(age) from table_name where group by age,sex;
#分组的意义在与更好的统计
foriindata.iloc[:100].groupby(by='客户省份'):
display(i[1])
data.groupby(by='客户省份').__dict__
add_prefix()添加前缀
pd.DataFrame(data.groupby(by='客户省份').金额.sum()).add_prefix('总')
可以使用pd.merge()函数将聚合操作的计算结果添加到df的每一行使用groupby分组后调用加和等函数进行运算,让后最后可以调用add_prefix(),来修改列名。
可以使用transform和apply实现相同功能
在transform或者apply中传入函数即可
data.groupby(by=['客户省份']).金额.agg(sum).sort_values()
5.2 离散化和分箱
字符型和范围型
方便观察和统计
pd.cut(),映射成一个范围类型
投票选举的例子就自己练习哦
5.3 一些概念
时间序列
时间类型是连续型
时间可以当作行索引
把字符串的时间转变为时间类型: pd.to_datetime()
s = pd.Series(['3/11/2000', '3/12/2000', '3/13/2000']*1000)
0 3/11/2000
1 3/12/2000
2 3/13/2000
3 3/11/2000
4 3/12/2000
5 3/13/2000
6 3/11/2000
....
pd.to_datatime(s)
0 2000-03-11
1 2000-03-12
2 2000-03-13
3 2000-03-11
4 2000-03-12
5 2000-03-13
6 2000-03-11
重采样
降采样 : 把高频的数据转换为低频的数据
数据量大,计算效率下降
数据不容易观察
要求行索引必须是时间序列
.resample()
Pandas中的resample,重新采样,是对原样本重新处理的一个方法,是一个对常规时间序列数据重新采样和频率转换的便捷的方法。
DataFrame.resample(rule, how``=``None``, axis``=``0``, fill_method``=``None``, closed``=``None``, label``=``None``, convention``=``'start'``,kind``=``None``, loffset``=``None``, limit``=``None``, base``=``0``)
6、大数据的读取
假如你待处理的数据比你的内存大怎么办?
#分片读取 skip() limit()
#skiprows=None (跳过多少行), nrows=None (获取多少行)
#查找最大值,每次读取100行
#把其它的最大金额给存储起来
max_data = []
#代表循环的次数
n = 0
while True:
if n == 0:
df = pd.read_excel('销售记录.xlsx',skiprows=n,nrows=100,header=None).iloc[1:]
max_data.append(df.iloc[:,-1].max())
else:
df = pd.read_excel('销售记录.xlsx',skiprows=n*100,nrows=100,header=None)
#dataframe中获取的数据大于1行
if df.shape[0] > 0:
max_data.append(df.iloc[:,-1].max())
else:
break
n += 1
np.max(max_data)