赞
踩
1.Series
2.DataFrame
3.从DataFrame中查询出Series
- import pandas as pd
- import numpy as np
Series是一种类似于一维数组的对象,它由一组数据〈不同数据类型)以及一组与之相关的数据标签(即索引)组成。
左侧为索引,右侧为数据
- s1=pd.Series([1,'x',5.7,7])
- #左侧为索引,右侧为数据
- s1
获取索引
s1.index
- 获取索引
- s1.index
获取数据
s1.values
- #获取数据
- s1.values
- s2=pd.Series([1,'x',5.7,7],index=['d','b','a','c'])
- s2
- s2.index
python字典和seires有着密不可分的关系
- sdata={'apple':35,'tex':40,'bananan':20,'pearl':30}
- s3=pd.Series(sdata)
- s3
----类似pthon的字典dict
- s2
- s2['a']
查一个数据得到是python原生的数据类型
- #查一个数据得到是python原生的数据类型
- type(s2['a'])
- s2[['b','a']]
查询Series的类型 type(s2[['b','a']])
- #查询Series的类型
- type(s2[['b','a']])
DataFrame是一个表格型的数据结构¶
①每列可以是不同的值类型(数值、字符串、布尔值等)
②既有行索引index,也有列索引columns
③可以被看做由Series组成的字典
④创建dataframe最常用的方法,见读取纯文本文件、excel、mysql数据库
列表中每个值的个数都必须相同
- #列表中每个值都必须相同
- data={
- 'state':['apple','tex','txt','banana','cxv'],
- 'year':[2000,1999,1998,1997,1996],
- 'pop':[1.1,1.2,1.3,1.4,1.5]
- }
- df=pd.DataFrame(data)
- df
- df.dtypes
- df.columns
- df.index
如果只查询一列,一行,返回的是pd.Series
如果查询多行、多列,返回的是pd.DataFrame
df
- df['state']
- type(df['year'])
- df[['pop','year']]
- type(df[['pop','year']])
loc(1)代表查询一行
- df.loc[1]
- type(df.loc[1])
列表中切片的操作方法去取,但是在Pandas中包括末尾元素
- #列表中切片的操作方法去取,但是在Pandas中包括末尾元素
- df.loc[1:3]
- type(df.loc[1:3])
总结:
1. pandas读取纯文本文件
·读取csv文件
·读取csv文件
2. pandas读取xlsx格式excel文件
3. pandas读取mysql数据表
- import pandas as pd
- fpath="./datas/ml-latest-small/ratings.csv"
- #注意是反斜杠/,不然会报错
注意:地址中是反斜杠/,不然会报错
使用pd.read_csv读取数据
ratings=pd.read_csv(fpath)
查看前几行的数据
ratings.head()
- #查看前几行的数据
- ratings.head()
查看数据的形状,返回(行数,列数)ratings.shape
- #查看数据的形状,返回(行数,列数)
- ratings.shape
查看列名列表
ratings.columns
- #查看列名列表
- ratings.columns
查看索引列
ratings.index
- #查看索引列
- ratings.index
查看每列的数据类型
ratings.dtypes
- #查看每列的数据类型
- ratings.dtypes
fpath2='./datas/crazyant/access_pvuv.txt'
- pvuv2=pd.read_csv(
- fpath2,
- sep='\t',
- header=None,
- names=['pdate','pv','pu']
- #注意设置列名的时候是names,而不是nameread_csv() got an unexpected keyword argument 'name'
- )
- pvuv2
注意:设置列名的时候是names,而不是name 报错:read_csv() got an unexpected keyword argument 'name'
- fpath3='./datas/crazyant/access_pvuv.xlsx'
- p3=pd.read_excel(fpath3)
- p3
- !pip install pymysql
- #使用的方法是read_sql
- import pymysql
使用的方法是read_sql:
- coon=pymysql.connect(
- host='127.0.0.1',
- user='root',
-
- database='test'
- charset='utf-8'
- )
- mysql_page=pd.read_sql('select * form crazyant_pvuv',con=coon)
注意:host是数据库的本地连接,user都是你本地电脑中设置的参数
Pandas查询数据的几种方法
1.df.loc方法,根据行、列的标签值查询
2. df.iloc方法,根据行、列的数字位置查询
3. df.where方法
4. df.query方法
.loc既能查询,又能覆盖写入,强烈推荐!
Pandas使用df.loc查询数据的方法
1.使用单个label值查询数据
2.使用值列表批量查询
3.使用数值区间进行范围查询
4.使用条件表达式查询
5.调用函数查询
·以上查询方法,既适用于行,也适用于列·注意观察降维dataFrame>Series>值
import pandas as pd
北京2018年全年天气预报
- df=pd.read_csv('./datas/beijing_tianqi/beijing_tianqi_2018.csv',index_col='ymd')
- df.head()
- df.index
设置索引为日期,方便按日期筛选
inplace=True 表示直接在原存储空间上进行更改,不是重新开辟一块空间进行更改
- #设置索引为日期,方便按日期筛选
- #inplace=True 表示直接在原存储空间上进行更改,不是重新开辟一块空间进行更改
- df.set_index('ymd',inplace=True)
- df.head()
替换掉温度后的℃
其实还是使用切片操作,首先筛选出所有的行,在筛选出yWendu中一列,带着类型replace修改完之后,在对修改后的类型进行转换
- df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')
- df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')
- df.head()
- df.dtypes
值得注意的是:
AttributeError: Can only use .str accessor with string values!这种错误一般都是修改完之后了,不能在进行修改,说明已经修改过了
行或列,都可以只传入单个值,实现精确匹配
查询一个单元格,只会返回一个数字值
- #查询一个单元格,只会返回一个数字值
- df.loc['2018-01-01','bWendu']
对于列的筛选,会产生一列,得到一个Series
- #对于列的筛选,会产生一列,得到一个Series
- df.loc['2018-01-01',['bWendu','yWendu']]
得到Series
- #得到Series
- df.loc[['2018-01-02','2018-01-03','2018-01-04'],'bWendu']
得到DataFrame
- #得到DataFrame
- df.loc[['2018-01-02','2018-01-03','2018-01-04'],['bWendu','yWendu']]
注意:区间既包括开始,也包括结束
行index按区间,切片操作的时候不用加双【】
列index按区间
行和列都按区间查询
- #行index按区间,切片操作的时候不用加双【】
- df.loc['2018-01-03':'2018-01-05','bWendu']
- #列index按区间
- df.loc['2018-01-03','bWendu':'fengxiang']
- #行和列都按区间查询
- df.loc['2018-01-03':'2018-01-05','bWendu':'fengxiang']
bool列表的长度等于行数或者列数
简单条件查询,最低温度低于-10度的列表
- #简单条件查询,最低温度低于-10度的列表
- df.loc[df['yWendu']<-10,:]
观察这里的boolean条件
- #观察这里的boolean条件
- df['yWendu']<-10
复杂条件查询,查完美天气
注意,组合条件&符号合并,每个条件判断都得带括号
查询最高温度小于30度,最低温度大于15度,晴天,天气为优的数据
- #查询最高温度小于30度,最低温度大于15度,晴天,天气为优的数据
- df.loc[(df['bWendu']<=30) & (df['yWendu']>=15) & (df['tianqi']=='晴') & (df['aqiLevel']==1),:]
观察这里boolean的条件
- #观察这里boolean的条件
- (df['bWendu']<=30) & (df['yWendu']>=15) & (df['tianqi']=='晴') & (df['aqiLevel']==1)
直接写lambda表达式
- # 直接写lambda表达式
- df.loc[lambda df :(df['bWendu']<=30)&(df['yWendu']>=15),:]
直接编写函数,查询9月份,空气质量好的数据
- #直接编写函数,查询9月份,空气质量好的数据
- def query_mydata(df):
- return df.index.str.startswith('2018-09')&df['aqiLevel']==1
- df.loc[query_mydata]
注意:
函数式编程的本质:函数自身可以像变量一样传递
在进行数据分析时,经常需要按照一定条件创建新的数据列,然后进行进一步分析
1.直接赋值
2. df.apply方法
3. df.assign方法
4.按条件选择分组分别赋值
import pandas as pd
- fpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'
- df=pd.read_csv(fpath)
- df.head()
清理温度列,变成一个数字类型
- df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')
-
- df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')
- df.head()
- #AttributeError: Can only use .str accessor with string values! 这种情况下语句代码只能运行一次,当运行第二次的时候,原存储的数据已经被改变了
需要注意的是:AttributeError: Can only use .str accessor with string values! 这种情况下语句代码只能运行一次,当运行第二次的时候,原存储的数据已经被改变了
将温差加入表格当中,注意wencha是一个series,后面的减法返回的是一个series
- df.loc[:,'wencha']=df['bWendu']-df['yWendu']
- df.head()
Apply a function along an axis of the DataFrame.
Objects passed to the function are Series objects whose index is either the DataFrame's index(axis=0) or the DataFrame's columns (axis=1).
实例:添加─列温度类型:
1.如果最高温度大于33度就是高温
2.低于-10度是低温
3.否则是常温
- def get_wendutype(x):
- if x['bWendu']>33:
- return '高温'
- if x['yWendu']<-10:
- return'低温'
- else:
- return '常温'
- df.loc[:,'wendutype']=df.apply(get_wendutype,axis=1)
df['wendutype'].value_counts()
Assign new columns to a DataFrame.
Returns a new object with all original columns in addition to new ones.
实例:将温度从摄氏度变成华氏度
注意:df.assign可以同时添加多个列
- #df.assign可以同时添加多个列
- df.assign(
- yWendu_huashi=lambda x: x['yWendu']*9/5+32,
-
- bWendu_huashi=lambda x: x['bWendu']*9/5+32
- )
按条件先选择数据,然后对这部分数据赋值新列
实例:高低温差大于10度,则认为温差大
- #先创建空列(第一种创建新列的方法)
- df['wencha']=''
- df.loc[df['bWendu']-df['yWendu']>10,'wencha']='温差大'
- df.loc[df['bWendu']-df['yWendu']<=10,'wencha']='温差正常'
- df['wencha'].value_counts()
1、汇总类统计
2、唯一去重和按值计数
3、相关系数和协方差
import pandas as pd
- fpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'
- df=pd.read_csv(fpath)
- df.head()
- df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')
- df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')
- df.head()
- #提取出所有数字列统计结果
- df.describe()
查看单个Series的数据---最高温度的平均值---df['bWendu'].mean()
- # 查看单个Series的数据---最高温度的平均值
- df['bWendu'].mean()
查看最高温度----df['bWendu'].max()
- #查看最高温度
- df['bWendu'].max()
最低温度----df['yWendu'].min()
- #最低温度
- df['yWendu'].min()
一般不用于数值列,而是枚举,分类列-----df[“ ” ].unique()
- df['fengxiang'].unique()
- df['tianqi'].unique()
- df['fengli'].unique()
- df['fengxiang'].value_counts()
- df['tianqi'].value_counts()
- df['fengli'].value_counts()
1.两只股票,是不是同涨同跌?程度多大?正相关还是负相关?
2.产品销量的波动,跟哪些因素正相关、负相关,程度有多大?
对于两个变量X、Y:
1.协方差︰衡量同向反向程度,如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;如果协方差为负,说明×,Y反向运动,协方差越小说明反向程度越高。
2.相关系数:衡量相似度程度,当他们的相关系数为1时,说明两个变量变化时的正向相似度最大,当相关系数为- 1时,说明两个变量变化的反向相似度最大¶
协方差矩阵-----df.cov()
- #协方差矩阵
- df.cov()
相关系数矩阵----df.corr()
- #相关系数矩阵
- df.corr()
单独查看空气质量和最高温度的相关系数----df['aqi'].corr(df['bWendu'])
- #单独查看空气质量和最高温度的相关系数
- df['aqi'].corr(df['bWendu'])
- df['aqi'].corr(df['yWendu'])
检测空气质量和温差的相关系数----df['aqi'].corr(df['bWendu']-df['yWendu'])
- #检测空气质量和温差的相关系数
- df['aqi'].corr(df['bWendu']-df['yWendu'])
以上就是特征方程对于机器学习重要性的一个例子
注:什么是特征方程?
特征方程是为研究相应的数学对象而引入的一些等式,它因数学对象不同而不同,包括数列特征方程、矩阵特征方程、微分方程特征方程、积分方程特征方程等等。
下面所介绍的仅仅是数列的特征方程。
一个数列:
设 有r,s使
所以
得
消去s就导出特征方程式
Pandas使用这些函数处理缺失值:
. isnull和notnull:检测是否是空值,可用于df和series.
dropna:丢弃、删除缺失值
axis:删除行还是列,{0 or 'index',1 or 'columns'}, default 0
how :如果等于any则任何值为空都删除,如果等于all则所有值都为空才删除
inplace :如果为True则修改当前df,否则返回新的df
. fillna:填充空值
value:用于填充的值,可以是单个值,或者字典(key是列名,value是值)
method :等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill
axis:按行还是列填充,{0 or 'index',1 or 'columns'}
inplace:如果为True则修改当前df,否则返回新的df
import pandas as pd
步骤1:读取excel的时候,忽略前几个空行
- fpath='./datas/student_excel/student_excel.xlsx'
- df=pd.read_excel(fpath,skiprows=2)
- df
步骤2:检测空值--df.isnull()
df.isnull()
以下两个函数输出的是相反的值:
df['分数'].isnull()、df['分数'].notnull()
- df['分数'].isnull()
- df['分数'].notnull()
筛选出没有空分数的所有行---df.loc[df['分数'].notnull(),:]
- #筛选出没有空分数的所有行
- df.loc[df['分数'].notnull(),:]
步骤3:删除掉全是空值的列
- df.dropna(axis='columns',how='all',inplace=True)
- df
步骤4:删除掉全是空值的行
- df.dropna(axis='index',how='all',inplace=True)
- df
步骤5:将分数列为空的填充为0分
df.fillna({'分数':0})
上述操作可以等于以下代码
- #上述操作可以等于一下代码
- df.loc[:,'分数']=df['分数'].fillna(0)
- df
步骤6:将姓名的缺失值填充
使用前面的有效值填充,用ffill:forward fill
- df.loc[:,'姓名']=df['姓名'].fillna(method='ffill')
- df
步骤7:将清洗号的excel保存
df.to_excel('./datas/student_excel/student_excel_clean.xlsx',index=False)
- fpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'
- df=pd.read_csv(fpath)
- df.head()
- df
- import pandas as pd
- df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')
- df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')
- df
只选出3月份的数据用来分析
- #只选出3月份的数据用来分析
- condition=df['ymd'].str.startswith('2018-03')
设置温差
- #设置温差
- df[condition]['wen_cha']=df['bWendu']-df['yWendu']
值得注意的是报错:
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead 发现:df[condition]['wen_cha']=df['bWendu']-df['yWendu']改句代码出错
这里我们也可以查看官网网站去完成差错:Indexing and selecting data — pandas 1.4.4 documentation (pydata.org)
查看是否修改成功
- #查看是否修改成功
- df[condition].head()
发出警告的代码: df[condition]['wen_cha']=df['bWendu']-df['yWendu']
相当于: df.get(condition).set(wen_cha),第一步的get发出了报警
链式操作其实是两个步骤,先get 后set,get得到的dateframe可能是View也可能是Copy、Pandas发出警告
【先可以去官网查看原因】
核心: pandas的dataframe的修改写操作,只允许在dataframe上进行,一步到位
将get+set 的两步操作,改成set的一步操作
- df.loc[condition,'wen_cha']=df['bWendu']-df['yWendu']
- df.head()
df[condition].head()
如果需要预选筛选数据做后续的处理分析,使用copy复制Dataframe
- df_month3=df[condition].copy()
- df_month3.head()
- df_month3['wen_cha']=df['bWendu']-df['yWendu']
- df_month3.head()
Series的排序:
Series.sort_values(ascending=True, inplace=False)
参数说明:
ascending:默认为True升序排序,为False降序排序.
inplace:是否修改原始Series
DataFrame的排序:
DataFrame.sort_values(by, ascending=True, inplace=False)
参数说明:
by:字符串或者List<字符串>,单列排序或者多列排序
ascending: bool或者List,升序还是降序,如果是list对应by的多列.
inplace:是否修改原始DataFrame
- import pandas as pd
- fpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'
- df=pd.read_csv(fpath)
- df
- df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')
- df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32
df.head()
df['aqi'].sort_values(ascending=False)
- ### 2、Series排序
- df['aqi'].sort_values(ascending=False)
默认为从低到高进行排序 df['aqi'].sort_values()
- #默认为从低到高进行排序
- df['aqi'].sort_values()
也可以对非数字序列进行排序——下述演示的是字符串序列进行排序 df['tianqi'].sort_values()
- #也可以对非数字序列进行排序——下述演示的是字符串序列进行排序
- df['tianqi'].sort_values()
默认天气状况从低到高进行排序 df.sort_values(by='aqi')
- #默认天气状况从低到高进行排序
- df.sort_values(by='aqi')
df.sort_values(by='aqi',ascending=False)
按空气质量等级、最高温度排序、默认升序
- #按空气质量等级、最高温度排序、默认升序
- df.sort_values(by=['aqiLevel','bWendu'])
两个字段都是降序排序 df.sort_values(by=['aqiLevel','bWendu'],ascending=False)
- #两个字段都是降序排序
- df.sort_values(by=['aqiLevel','bWendu'],ascending=False)
分别指定升序和降序
df.sort_values(by=['aqiLevel','bWendu'],ascending=[True,False])
- #分别指定升序和降序
- df.sort_values(by=['aqiLevel','bWendu'],ascending=[True,False])
前面我们已经使用了字符串的处理函数:
df["bWendu"].str.replace("℃","").astype('int32')Pandas的字符串处理:
1.使用方法:先获取Series的str属性,然后在属性上调用函数;
2.只能在字符串列上使用,不能数字列上使用;
3. Dataframe上没有str属性和处理方法
4.Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似;
内容如下:
1.获取Series的str属性,然后使用各种字符串处理函数
2.使用str的startswith、contains等bool类Series可以做条件查询
3.需要多次str处理的链式操作
4.使用正则表达式的处理
- import pandas as pd
- fpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'
- df=pd.read_csv(fpath)
- df.head()
df.dtypes
获取最高温度的Series的温度列
- #获取最高温度的Series的温度列
- df['bWendu'].str
字符串替换函数
- #字符串替换函数
- df['bWendu'].str.replace('℃','')
判断是不是数字
- #判断是不是数字
- df['bWendu'].str.isnumeric()
- df['aqi'].str.len()
- #AttributeError: Can only use .str accessor with string values! len()方法只能用于字符串类型的数据
AttributeError: Can only use .str accessor with string values! len()方法只能用于字符串类型的数据
Pandas startswith()是另一种在系列或 DataFrame 中搜索和过滤文本数据的方法。此方法类似于Python的startswith()方法,但参数不同,并且仅适用于Pandas对象。因此,.str必须在每次调用此方法之前加上前缀,以便编译器知道它与默认函数不同。
用法:Series.str.startswith(pat, na=nan)
参数:
pat:要搜索的字符串。 (不接受正则表达式)
na:用于设置序列中的值为NULL时应显示的内容。
返回类型:布尔序列,为True,其中值的开头是传递的字符串。
从ymd这一列挑选出2018-03这类型的数据,返回的是一个Boolean类型
- #从ymd这一列挑选出2018-03这类型的数据,返回的是一个Boolean类型
- condition=df['ymd'].str.startswith('2018-03')
- condition
输出在condition条件下的df中的数据
- #输出在condition条件下的df中的数据
- df[condition].head()
1、先将日期2018-03-31替换成20180331的形式
2、提取月份字符串201803
df['ymd'].str.replace('-','')
问题:直接在Series上面调用方法的话,是否可行?
答:不可行
原因:每次调用函数,都会返回一个新的series
df['ymd'].str.replace('-','').slice(0,6)
'Series' object has no attribute 'slice'---意思就是series不能够直接去调用slice函数,必须经过str调用后才可以使用
- #原因:每次调用函数,都会返回一个新的series
- df['ymd'].str.replace('-','').slice(0,6)
- #'Series' object has no attribute 'slice'---意思就是series不能够直接去调用slice函数,必须经过str调用后才可以使用
df['ymd'].str.replace('-','').str.slice(0,6)
slice是切片操作,也可以直接为str[0:6]
- #slice是切片操作,也可以直接为str[0:6]
- df['ymd'].str.replace('-','').str[0:6]
- #添加新列
- def get_riqi(x):
- year,month,day=x['ymd'].split('-')
- return f'{year}年{month}月{day}日'
- df['中文日期']=df.apply(get_riqi,axis=1)
- df['中文日期']
new question? -----如何将日期中,年月日三个字去除
方法1:链式replace
- #方法1:链式replace
- df['中文日期'].str.replace('年','').str.replace('月','').str.replace('日','')
Series.str默认开启了正则表达式模式
方法2:正则表达式替换
- #方法2:正则表达式替换
- df['中文日期'].str.replace('[年月日]','',regex=True)
注:
The default value of regex will change from True to False in a future version.
在Pandas未来的版本中,.str.replace() 的regex的默认值将从True变为False
而当regex=True时,单字符正则表达式不会被视为文本字符串
因为我们是针对price中两个单个字符进行操作,因此设置regex=True
. axis=O或者"index":
·如果是单行操作,就指的是某一行
·如果是聚合操作,指的是跨列cross columns
. axis=1或者"columns":
-如果是单列操作,就指的是某一列
·如果是聚合操作,指的是跨列cross columns
按哪个axis,就是这个axis要动起来(类似被or遍历),其它的axis保持不动
- import pandas as pd
- import numpy as np
- df=pd.DataFrame(
- np.arange(12).reshape(3,4),
- columns=['A','B','C','D']
- )
- df
代表的就是删除某列
- #代表的就是删除某列
- df.drop('A',axis=1)
代表的就是删除某行
- #代表的就是删除某行
- df.drop(1,axis=0)
并不是像我们想象的那个样子,输出的是每列的结果!!!
axis=0 or axis=index
- # axis=0 or axis=index
- df.mean(axis=0)
指定了按那个axis,就是这个axis要动起来(类似被for遍历),其他的axis保持不动
并不是像我们想象的那个样子,输出的是每行的结果!!
axis=1 or axis=colums
- # axis=0 or axis=colums
- df.mean(axis=1)
指定了按那个axis,就是这个axis要动起来(类似被for遍历),其他的axis保持不动
- def get_sum(x):
- return x['A']+x['B']+x['C']+x['D']
- df['sum']=df.apply(get_sum,axis=1)
- df
- #跨列相加
Pandas的索引index的用途:
把数据存储于普通的column列也能用于数据查询,那使用index有什么好处?
index的用途总结:
1.更方便的数据查询;
2.使用index可以获得性能提升;
3.自动的数据对齐功能;
4.更多更强大的数据结构支持;
- import pandas as pd
- df=pd.read_csv('./datas/ml-latest-small/ratings.csv')
- df.head()
查询index的数量:df.count()
df.count()
drop==False,让索引列还保持在column:意思就是使id这一列继续存在于数据当中
- #drop==False,让索引列还保持在column:意思就是使id这一列继续存在于数据当中
- df.set_index('userId',inplace=True,drop=False)
- df.head()
df.index
第一种:使用index查询的方法---会使查询的代码比较简单
df.loc[500].head()
- #第一种:使用index查询的方法---会使查询的代码比较简单
- df.loc[500].head()
第二种:使用column的condition查询方法
condition=df['userId']
df.loc[condition==500].head()
- #第二种:使用column的condition查询方法
- condition=df['userId']
- df.loc[condition==500].head()
如果index是唯一的,Pandas会使用哈希表优化,查询性能为O(1);
如果index不是唯一的,但是有序,Pandas会使用二分查找算法,查询性能为O(logN);
如果index是完全随机的,那么每次查询都要扫描全表,查询性能为O(N);
将数据随机打散
- !pip install sklearn
- #将数据随机打散
- from sklearn.utils import shuffle
- df_shuffle=shuffle(df)
- df_shuffle.head()
查询我们的索引是不是递增的
df_shuffle.index.is_monotonic_increasing
- #查询我们的索引是不是递增的
- df_shuffle.index.is_monotonic_increasing
查询我们的索引是不是递减的
df_shuffle.index.is_monotonic_decreasing
- #查询我们的索引是不是递减的
- df_shuffle.index.is_monotonic_decreasing
%timeit 函数是经过大量运算,统计计算出平均运行所用的时间
计时,查询id==500数据性能
%timeit df_shuffle.loc[500]
- # %timeit 函数是经过大量运算,统计计算出平均运行所用的时间
- # 计时,查询id==500数据性能
- %timeit df_shuffle.loc[500]
调用sort函数默认为升序操作
- #调用sort函数默认为升序操作
- df_sorted=df_shuffle.sort_index()
- df_sorted.head()
- df_sorted.index.is_monotonic_increasing
调用sort函数默认为降序操作 设置为ascending=False为降序操作
- #调用sort函数默认为降序操作 设置为ascending=False为降序操作
- df_sorted2=df_shuffle.sort_index(ascending=False)
- df_sorted2.index.is_monotonic_decreasing
判断索引是不是唯一的
df_sorted.index.is_unique
- #判断索引是不是唯一的
- df_sorted.index.is_unique
如果index不是唯一的,但是有序,Pandas会使用二分查找算法,查询性能为O(logN);
%timeit df_sorted.loc[500]
- #如果index不是唯一的,但是有序,Pandas会使用二分查找算法,查询性能为O(logN);
- %timeit df_sorted.loc[500]
包括series和dataframe
index会自动对齐
- #index会自动对齐
- s1=pd.Series([1,2,3],index=list('abc'))
- s1
- s2=pd.Series([2,3,4],index=list('bcd'))
- s2
当s1+s2中遇到另一方没有找到相同的索引时,会显示NaN,无法进行算术操作时
- #当s1+s2中遇到另一方没有找到相同的索引时,会显示NaN,无法进行算术操作时
- s1+s2
很多强大的索引数据结构
Categoricallndex,基于分类数据的Index,提升性能;
Multilndex,多维索引,用于groupby多维聚合后结果等;
Datetimelndex,时间类型索引,强大的日期和时间的方法支持;
Pandas的Merge,相当于Sql的Join,将不同的表按key关联到一个表
pd.merge(left,right, how='nner , on=None,left_on=None, right_on=None,lef_index=False,right_index=False,sort=True, sufises=(‘_X’ ,“_Y” ), opy=Tue,indicator=False, validate=None)
left,right:要merge的dataframe或者有name的Series.
how: join类型,'left', 'right', 'outer', 'inner'
on: join的key,left和right都需要有这个key.
left_on: left的df或者series的key
right_on: right的df或者seires的key
left_index,right_index:使用index而不是普通的column做join
suffixes:两个元素的后缀,如果列有重名,自动添加后缀,默认是('_X','_y')
本次讲解提纲:
1.电影数据集的join实例
2.理解merge时一对一、一对多、多对多的数量对齐关系
3.理解left join、right join、inner join、outer join的区别
4.如果出现非Key的字段重名怎么办
- import pandas as pd
- df_ratings=pd.read_csv(
- './datas/movielens-1m/ratings.dat',
- sep="::",#设置其分隔服为::
- engine='python',#因为pandas语法中sep为两个字符的时候,系统默认其为正则表达式,但是分隔符就是::不是正则表达式,所以加engine=python
- names='UserID::MovieID::Rating::Timestamp'.split('::')
- )
- df_ratings.head()
- df_users=pd.read_csv(
- './datas/movielens-1m/users.dat',
- sep="::",
- engine='python',
- names='UserID::Gender::Age::Occupation::Zip-code'.split('::')
- )
- df_users.head()
- df_movies=pd.read_csv(
- './datas/movielens-1m/movies.dat',
- sep='::',
- engine='python',
- names='MovieID::Tile::Genres'.split("::")
- )
- df_movies.head()
- df_ratings_users=pd.merge(
- df_ratings,df_users,on='UserID',how='inner'
- )
- df_ratings_users.head()
- df_ratings_users_movies=pd.merge(
- df_ratings_users,df_movies,left_on='MovieID',right_on='MovieID',how='inner'
- )
- df_ratings_users_movies.head()
. one-to-one:—对一关系,关联的key都是唯一的
.比如(学号,姓名) merge (学号,年龄)
-结果条数为:1*1
. one-to-many:一对多关系,左边唯一key,右边不唯一key
-比如(学号,姓名) merge(学号,[语文成绩、数学成绩、英语成绩])
结果条数为:1*N
. many-to-many : [多对多关系,左边右边都不是唯一的
·比如(学号,[语文成绩、数学成绩、英语成绩])merge (学号,[篮球、足球、乒乓球)
-结果条数为:M*N
- left=pd.DataFrame({
- 'sno':[11,12,13,14],
- 'name':['name_a','name_b','name_c','name_d']
- }
- )
- left
- right=pd.DataFrame({
- 'sno':[11,12,13,14],
- 'age':['21','22','23','24']
- })
- right
- #一对一关系中:结果有四条
- pd.merge(left,right,on='sno')
merge注意:数据会被制
- left=pd.DataFrame({
- 'sno':[11,12,13,14],
- 'name':['name_a','name_b','name_c','name_d']
- }
- )
- left
- right=pd.DataFrame({
- 'sno':[11,11,11,12,12,13],
- 'grade':['英语:21','语文:22','数学:23','英语:24',"语文:11","数学:55"]
- })
- right
- #一对多的关系对name名字进行了复制
- pd.merge(left,right,on='sno')
注意:结果数量会出现乘法
- left=pd.DataFrame({
- 'sno':[11,11,12,12,12],
- '爱好':['篮球','羽毛球','乒乓球','篮球','足球']
- }
- )
- left
- right=pd.DataFrame({
- 'sno':[11,11,11,12,12,13],
- 'grade':['英语:21','语文:22','数学:23','英语:24',"语文:11","数学:55"]
- })
- right
pd.merge(left,right,on='sno')
- left=pd.DataFrame({
- 'key':['ko','k1','k2','k3'],
- 'A':['A0','A1','A2','A3'],
- 'B':['B0','B1','B2','B3']
- })
- right=pd.DataFrame({
- 'key':['k0','k1','k2','k3'],
- 'C':['C0','C1','C2','C3'],
- 'D':['D0','D1','D2','D3']
-
- })
- left
左边和右边的key都有,才会出现在结果里
pd.merge(left,right,how='inner')
左边的都会出现在结果里,右边的如果无法匹配则为Null
pd.merge(left,right,how='left')
右边的都会出现在结果里,左边的如果无法匹配则为Nul
pd.merge(left,right,how='right')
左边、右边的都会出现在结果里,如果无法匹配则为Null
pd.merge(left,right,how='outer')
- left=pd.DataFrame({
- 'key':['K0','k1','k2','k3'],
- 'A':['A0','A1','A2','A3'],
- 'B':['B0','B1','B2','B3']
- })
- right=pd.DataFrame({
- 'key':['K0','K1','K4','K5'],
- 'A':['A10','A11','A12','A13'],
- 'D':['D0','D1','D4','D5']
- })
- left
pd.merge(left,right,on='key')
suffixes=('name1','name2')可以直接设置重名函数的函数名
pd.merge(left,right,on='key',suffixes=('_left','_right'))
- #suffixes=('name1','name2')可以直接设置重名函数的函数名
- pd.merge(left,right,on='key',suffixes=('_left','_right'))
使用场景:
批量合并相同格式的Excel、给DataFrame添加行、给DataFrame添加列
一句话说明concat语法:
。使用某种合并方式(inner/outer)
·沿着某个轴向(axis=0/1)
·把多个Pandas对象(DataFrame/Series)合并成一个。
concat语法: pandas.concat(objs, axis=0, join='outer', ignore_index=False)
. objs: 一个列表,内容可以是DataFrame或者Series,可以混合
. axis: 默认是0代表按行合并,如果等于1代表按列合并
. join:合并的时候索引的对齐方式,默认是outer join,也可以是inner join.
ignore_index:是否忽略掉原来的数据索引
append语法: DataFrame.append(other, ignore_index=False)
append只有按行合并,没有按列合并,相当于concat按行的简写形式.
other:单个dataframe、series、dict,或者列表
ignore_index:是否忽略掉原来的数据索引
- import pandas as pd
- import warnings
- warnings.filterwarnings('ignore')
- df1=pd.DataFrame({
- 'A':['A0','A1','A2','A3'],
- 'B':['B0','B1','B2','B3'],
- 'C':['C0','C1','C2','C3'],
- 'D':['D0','D1','D2','D3'],
- 'E':['E0','E1','E2','E3']
- })
- df2=pd.DataFrame({
- 'A':['A4','A5','A6','A7'],
- 'B':['B4','B5','B6','B7'],
- 'C':['C4','C5','C6','C7'],
- 'D':['D4','D5','D6','D7'],
- 'F':['F4','F5','F6','F7']
- })
- df1
df2
因为默认axis=0,即第二个df2的值默认放在第一个df1内容的下面,即所谓的行合并
pd.concat([df1,df2])
- #因为默认axis=0,即第二个df2的值默认放在第一个df1内容的下面,即所谓的行合并
- pd.concat([df1,df2])
忽略原来的缩影的列,从0,1,2,3........
pd.concat([df1,df2],ignore_index=True)
意思就是只要任意一组没有就进行过滤
pd.concat([df1,df2],ignore_index=True,join='inner')
- #意思就是只要任意一组没有就进行过滤
- pd.concat([df1,df2],ignore_index=True,join='inner')
df1
- s1=pd.Series(list(range(4)),name='F')
- s1
- pd.concat([df1,s1],axis=1)
- s2=df1.apply(lambda x:x["A"]+'_11',axis=1)
- s2
- s2.name='G'
- pd.concat([df1,s1,s2],axis=1)
- #列表中可以只有Series
- pd.concat([s1,s2],axis=1)
- #列表也可以是混合顺序的
- pd.concat([s1,df1,s2],axis=1)
- df1=pd.DataFrame([[1,2],[3,4]],columns=list('AB'))
- df1
- df2=pd.DataFrame([[5,6],[7,8]],columns=list('AB'))
- df2
df1.append(df2)
df1.append(df2,ignore_index=True)
- #一个空的df
- df=pd.DataFrame(columns=['A'])
- df
- for i in range(5):
- #利用这种循环,每次都在复制
- df=df.append({'A':i},ignore_index=True)
- df
- #第一个入参的是列表,避免了多次的复制,直接往里面添加就可以了
- pd.concat(
- [pd.DataFrame([i],columns=['A']) for i in range(5)],
- ignore_index=True
- )
实例演示:
1.将一个大Excel等份拆成多个Excel
2.将多个小Excel合并成一个大Excel并标记来源
- #本节课的数据目录work_dir
- work_dir='./course_datas/c15_excel_split_merge'
- #work_dir下面的splits目录,来放置拆分后的小文件
- splits_dir=f'{work_dir}/splits'
- import os
- #如果splits_dir目录不存在就创建一个小目录
- if not os.path.exists(splits_dir):
- os.mkdir(splits_dir)
- import pandas as pd
- df_source=pd.read_excel(f'{work_dir}/crazyant_blog_articles_source.xlsx')
- df_source.head()
- df_source.index
- df_source.shape
- total_row_count=df_source.shape[0]
- total_row_count
1.使用df.iloc方法,将一个人的dataframe,拆分成多个小dataframe
2.将使用dataframe.to_excel保存每个小Excel
- #将一个大的EXCEL文件拆分给这几个人
- user_name=['xiaohu','xiaoshuai','xiaolan','xiaofan','xiaok','xiaom']
- #每个人的任务数目
- splits_size=total_row_count//len(user_name)
- #判断每个人分配的任务数是否为整数,若不为整数则+1
- if total_row_count % len(user_name) !=0:
- splits_size+=1
- splits_size
- #将拆出来的小的dataframe存在df_sub[]当中
- df_subs=[]
- for index,user_name in enumerate(user_name):
- #iloc的开始索引,从0开始进行索引
- begin=index*splits_size
- #iloc的结束索引
- end=begin+splits_size
- #实现df按照iloc拆分
- df_sub=df_source.iloc[begin:end]
- #将每个子df存入列表
- df_subs.append((index,user_name,df_sub))
- for index,user_name,df_sub in df_subs:
- file_name=f'{splits_dir}/crazyant_blog_articles_{index}_{user_name}.xlsx'
- df_sub.to_excel(file_name,index=False)
1.遍历文件夹,得到要合并的Excel文件列表
2.分别读取到dataframe,给每个df添加—列用于标记来源
3.使用pd.concat进行df批量合并
4.将合并后的dataframe输出到excel
- import os
- excel_names=[]
- for excel_name in os.listdir(splits_dir):
- excel_names.append(excel_name)
- excel_names
- #os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。
- df_list=[]
- for excel_name in excel_names:
- #将每个excel读取到df当中
- excel_path=f'{splits_dir}/{excel_name}'
- df_split=pd.read_excel(excel_path)
- #得到username
- username=excel_name.replace('crazyant_blog_articles_','').replace('.xlsx','')[2:]
- print(excel_name,username)
- #给每个df添加1列,即用户名字
- df_split['username']=username
- df_list.append(df_split)
- df_merged=pd.concat(df_list)
- df_merged.shape
- df_merged.head()
df_merged['username'].value_counts()
df_merged.to_excel(f'{work_dir}/crazyant_blog_articles_merged.xlsx',index=False)
类似SQL: select city,max(temperature) from city_weather group by city;
groupby:先对数据分组,然后在每个分组上应用聚合函数、转换函数
一、分组使用聚合函数做数据统计
二、遍历groupby的结果理解执行流程
三、实例分组探索天气数据
- import pandas as pd
- import numpy as np
- #在jupyter notebook中展示matplot图表
- %matplotlib inline
- df=pd.DataFrame({
- 'A':['foo','bar','foo','bar','foo','bar','foo','foo'],
- 'B':['one','one','two','three','one','one','two','three'],
- 'C':np.random.randn(8),
- 'D':np.random.randn(8)
- })
- df
- P=df.groupby('A').sum()
- #聚合操作后P仍然是一个Dataframe
- P
df.groupby('name').sum()
Ps: 1、将name列的不同名称作为索引
- 2、忽略df中不是数字列的一列
-
- 3、对是数字列的一列进行累加
-
- 4、统计在name不同名称下的,其他值的和
df.groupby(['A','B']).mean()
1、选取A、B两列的不同名称作为索引---在这里因为A列的bar没有B列中的two所以没有
2、对数字列进行求取平均值
3、统计在不同名下的平均值
4、将A、B变成二级索引
- #设置as_index=False,取消A、B作为二级索引
- df.groupby(['A','B'],as_index=False).mean()
df.groupby('A').agg([np.sum,np.mean,np.std])
1、将name列的不同名称作为索引
- 2、忽略df中不是数字列的一列
-
- 3、对是数字列的一列进行操作
-
- 4、统计在name不同名称下的,其他值的和
列变成了多级索引
- #方法1:预过滤,性能更好
- df.groupby('A')['C'].agg([np.sum,np.mean,np.std])
- #方法2:
- df.groupby('A').agg([np.sum,np.mean,np.std])['C']
- df.groupby('A').agg({
- 'C':np.sum,
- 'D':np.mean
- })
for循环可以直接遍历每个group
- g=df.groupby('A')
- g
- #相当于对A索引的不同值的列进行一个汇总,使数据看起来更加的清晰
- for name,group in g:
- print(name)
- print(group)
- print( )
可以获取单个分组的数据
g.get_group('bar')
- g=df.groupby(['A','B'])
- for name,group in g:
- print(name)
- print(group)
- print( )
- #name 是一个2个元素的元组,代表不同的列
可以直接查询group后的某几列,生成Series或者子DataFrame
- g['C']
- for name,group in g:
- print(name)
- print(group)
- print( )
本质:所有的聚合统计,都是在dataframe和series上进行的
- fpath='./datas/beijing_tianqi/beijing_tianqi_2018.csv'
- df=pd.read_csv(fpath)
- df
- #替换掉温度后缀℃
- df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','')
- df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','')
- df
- df2=df.drop(labels=['bWendu','yWendu'], axis=0, inplace=False)
- df2
- df2.loc[:,'bWendu']=df2['bWendu'].astype('int32')
- df2.loc[:,'yWendu']=df2['yWendu'].astype('int32')
- df2.head()
- #新增一列为月份
- df['month']=df['ymd'].str[:7]
- df.head()
- data=df.groupby('month')['bWendu'].max()
- data
- type(data)
- data=data.astype(float)
- data.plot()
- df.head()
- group_data=df.groupby('month').agg({'bWendu':np.max,'yWendu':np.min,'aqi':np.mean})
- group_data
group_data.plot()
1为什么要学习分层索引Multilndex?
1、分层索引:在一个轴向上拥有多个索引层级,可以表达更高维度数据的形式;
2、方便的进行数据筛选,如果有序则性能更好;
3、groupby等操作的结果,如果是多KEY,结果是分层索引,需要会使用。
4、一般不需要自己创建分层索引(Multilndex有构造函数但一般不用)
演示数据:百度、阿里巴巴、爱奇艺、京东四家公司的10天股票数据数据来自:英为财经
—、Series的分层索引Multilndex
二、Series有多层索引怎样筛选数据?
三、DataFrame的多层索引Multilndex
四、DataFrame有多层索引怎样筛选数据?
- import pandas as pd
- %matplotlib inline
- stocks=pd.read_excel('./datas/stocks/互联网公司股票.xlsx')
- stocks.shape
stocks
- stocks['公司'].unique()
- stocks.index
- #计算每个公司收盘的平均值
- stocks.groupby('公司')['收盘'].mean()
- ser=stocks.groupby(['公司','日期'])['收盘'].mean()
- ser
ser.index
- # unstack把二级索引变成列
- ser.unstack()
- ser
- #全部变成一维的普通索引模式
- ser.reset_index()
- ser
- ser.loc['BIDU']
- # 多层索引,可以用元组的形式进行筛选
- ser.loc[('BIDU','2019-10-02')]
- #求所有公司中指定月份的收盘价
- ser.loc[:,'2019-10-02']
- stocks.head()
- stocks.set_index(['公司','日期'],inplace=True)
- stocks
- stocks.index
- #自动根据索引进行排序,默认为升序排列
- stocks.sort_index(inplace=True)
- stocks
【重要知识】在选择数据时:
。元组(key1.key2)代表筛选多层索引,其中key1是索引第一级,key2是第二级,比如key1=JD, key2=2019-10-02
·列表[key1,key2]代表同一层的多个KEY,其中key1和key2是并列的同级索引,比如key1=JD, key2=BIDU
stocks.loc['BIDU']
- # 'BIDU'是一级索引 '2019-10-02'是二级索引
- stocks.loc[('BIDU','2019-10-02'),:]
stocks.loc[('BIDU','2019-10-02'),'开盘']
- #设置日期的同一级索引的格式
- stocks.loc[('BIDU',['2019-10-03','2019-10-02']),'收盘']
- #slice(None)代表筛选中一索引的所有内容---在这里的意思就是筛选一级索引‘公司’的所有内容
- stocks.loc[(slice(None),['2019-10-03','2019-10-02']),:]
- #将多重索引全部重置,转换为一维索引
- stocks.reset_index()
数据转换函数对比: map、apply、applymap
实例:将股票代码英文转换成中文名字
Series.map(dict) or Series.map(function)均可
- import pandas as pd
- stocks=pd.read_excel('./datas/stocks/互联网公司股票.xlsx')
- stocks.head()
stocks['公司'].unique()
- #公司股票代码到中文的映射,注意这里要小写
- dict_company_names={
- 'bidu':'百度',
- 'baba':'阿里巴巴',
- 'iq':'爱奇艺',
- 'jd':'京东'
- }
方法1:Series.map(dict) ----在map函数中传进去一个字典只用于Series
- # stocks['公司'].str.lower()---将公司中的所有字母转换为小写字母
- # .map(dict_company_names)--把公司中所有对应的列转换为其对应的中文字母
- stocks['公司中文1']=stocks['公司'].str.lower().map(dict_company_names)
- stocks.head()
方法2:Series.map(function) ----在map函数中传进去一个自定义函数只用于Series
function的参数是Series的每个元素的值
- stocks['公司中文2']=stocks['公司'].map(lambda x:dict_company_names[x.lower()])
- stocks.head()
Series.apply(function),函数的参数是每个值.
DataFrame.apply(function),函数的参数是Series
Series.apply(function)
function的参数是Series的每个值
- stocks['公司中文3']=stocks['公司'].apply(
- lambda x:dict_company_names[x.lower()]
- )
- stocks.head()
function的参数是对应轴的Series
- stocks['公司中文4']=stocks.apply(
- lambda x:dict_company_names[x['公司'].lower()],
- axis=1
- )
- stocks.head()
注意这个代码:
- 1、apply是在stocks这个DataFrame上调用;
-
- 2、lambda x的x是一个Series,因为指定了axis=1所以Seires的key是列名,可以用x[公司"]获取
- sub_df=stocks[['收盘','开盘','高','低','交易量']]
- sub_df.head()
- #将这些数字取整数,应用于所有元素
- sub_df.applymap(lambda x:int(x))
- #直接修改原df的这几列
- stocks.loc[:,['收盘','开盘','高','低','交易量']]=sub_df.applymap(lambda x:int(x))
- stocks.head()
知识:Pandas的GroupBy遵从split、apply.combine模式
这里的split指的是pandas的groupby,我们自己实现apply函数,apply返回的结果由pandas进行combine得到结果
GroupBy.apply(function)
. function的第一个参数是dataframe
. function的返回结果,可是dataframe、series、单个值,甚至和输入dataframe完全没关系
本次内容:
1.怎样对数值列按分组的归—化?
2.怎样取每个分组的TOPN数据?
实例1:怎样对数值列按分组的归一化?
将不同范围的数值列进行归一化,映射到[0,1]区间:
·更容易做数据横向对比,比如价格字段是几百到几千,增幅字段是0到100
·机器学习模型学的更快性能更好
归一化的公式:
演示:用户对电影评分的归一化
每个用户的评分不同,有的乐观派评分高,有的悲观派评分低,按用户做归—化
- import pandas as pd
- ratings=pd.read_csv(
- './datas/movielens-1m/ratings.dat',
- sep='::',
- engine='python',
- names='UserID::MovieID::Rating::Timestamp'.split('::')
-
- )
- ratings.head()
- #实现按照用户ID分组,然后对其中一列进行归一化
- def ratings_room(df):
- '''
- 每个用户分组的dataframe
- '''
- min_value=df['Rating'].min()
- max_value=df['Rating'].max()
- df['Rating_rooms']=df['Rating'].apply(
- lambda x:(x-min_value)/(max_value-min_value)
- )
- return df
-
- ratings=ratings.groupby('UserID').apply(ratings_room)
- ratings.head()
ratings[ratings['UserID']==1].head()
看到UserID==1这个用户,Rating==3是他的最低分,是个乐观派,我们归一化到0分
获取2018年每个月温度最高的2天数据
- df=pd.read_csv(
- './datas/beijing_tianqi/beijing_tianqi_2018.csv'
- )
- df.loc[:,'bWendu']=df['bWendu'].str.replace('℃','').astype('int32')
- df.loc[:,'yWendu']=df['yWendu'].str.replace('℃','').astype('int32')
- #创建一个新的列为月份列
- df['month']=df['ymd'].str[:7]
- df
- def getWenduTopn(df,topn):
- '''
- 这里的df,是每个月份分组的group的df
- '''
- df2=df.sort_values(by='bWendu')[['ymd','bWendu']][-topn:]
- return df2
- df.groupby('month').apply(getWenduTopn,topn=2).head()
将列式数据变成二维交叉形式,便于分析,叫做重塑或透视
1.经过统计得到多维度指标数据
2.使用unstack实现数据二维透视
3.使用pivot简化透视
4.stack、unstack、pivot的语法
非常场景的统计场景,指定多个维度,计算聚合后的指标
实例:统计得到"电影评分数据集”,每个月份的每个分数被评分多少次:(月份、分数1~5、次数)
- import pandas as pd
- import numpy as np
- %matplotlib inline
- df=pd.read_csv(
- './datas/movielens-1m/ratings.dat',
- sep='::',
- engine='python',
- names='UserID::MovieID::Rating::Timestamp'.split('::')
-
- )
- df.head()
- df['pdata']=pd.to_datetime(df['Timestamp'],unit='s')
- df.head()
df.dtypes
- #实现数据统计
- df_group=df.groupby([df['pdata'].dt.month,'Rating'])['UserID'].agg(pv=np.sum)
- df_group.head()
对于这样的格式数据,查看按月份,不同评分的次数趋势,是没法实现的
需要将数据变换成每个评分是一列才可以实现
目的:想要画图对比按照月份的不同评分的数量趋势
- df_stack=df_group.unstack()
- df_stack
df_stack.plot()
- #unstack和stack是互逆操作
- df_stack.stack().head()
df_group.head()
- df_reset=df_group.reset_index()
- df_reset.head()
- #因为是二维的---pdata代表x轴,Rating代表y轴,pv代表数据
- df_pivot=df_reset.pivot('pdata','Rating','pv')
- df_pivot.head()
df_pivot.plot()
stack: DataFrame.stack(level=-1, dropna=True),将column变成index,类似把横放的书籍变成竖放
level=-1代表多层索引的最内层,可以通过==0、1、2指定多层索引的对应层
unstack: DataFrame.unstack(level=-1, fill_value=None),将index变成column,类似把竖放的书籍变成横放
pivot: DataFrame.pivot(index=None , columns=None, values=None),指定index、columns、values实现二维透视¶
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。