Pandas
一.Pandas读取数据
数据类型 | 说明 | Pandas读取方法 |
---|---|---|
excel | 微软xls或者xlsx文件 | pd.read_excel |
csv、tsv、txt | 用逗号分隔、tab分割的纯文本文件 | pd.read_csv |
mysql | 关系型数据库表 | pd.read_sql |
1.1有规律的CSV
import pandas as pd fpath = "需要打开的文件路径" ratings = pd.read_csv(fpath) # 查看前几行数据 ratings.head()
# 查看数据的形状,返回(行数,列数) ratings.shape # (100836,4) # 查看列名列表 ratings.columns # Index(['userId' , 'movieId', 'rating', 'timestamp’],dtype='object') # 查看索引列 ratings.index # RangeIndex(start=0,stop=100836,step=1) # 查看每列的数据类型 ratings.dtypes
1.2无格式TXT
fpath = "text文件路径" pvuv = pd.read_csv( fpath, # 文件路径 sep="\t", # 指定列的分隔符 header=None, # 文件无标题行 names=['A','B','C'], # 自己指定列名 ) print(pvuv)
1.3Excel
fpath = "excel文件路径" pvuv = pd.read_excel(fpath) print(pvuv)
1.4读取数据库
import pymysql # 使用pymysql连接数据库 conn = pymysql.connect( host=’127.0.0.1’, user='root', password='12345678’, database='test', charset='utf8', ) # 输入 sql 语法查询表 con = conn 选择连接的库 mysql_page = pd.read_sq1("select * from crazyant_pvuv",con = conn) print(mysql_page)
二、Pandas数据结构
DataFrame (二维) ====》Series(一维) 类似字典更容易处理
import pandas as pd import numpy as np
1.Series
Series是一种类似于一维数组的对象,它由一组数据〈不同数据类型)以及一组与之相关的数据标签(即索引)组成。
sl = pd.Series([1,'a',5.2,7]) # 左侧为索引,右侧是数据 print(s1) # 索引为默认数字序列 0 1 .... n # 获取序列 s1.index # 获取数据 s1.values
# 自定义索引 s1 = pd.Series([1, 2, 3], index=['name', 'age', 'adress']) print(s1) #>>> name 1 # age 2 # adress 3 # dtype: int64 # 使用"字典"访问数据 s1['name'] s1['age', 'name']
2.DataFrame
DataFrame是一个表格型的数据结构
-
每列可以是不同的值类型(数值、字符串、布尔值等)
-
既有行索引lindex,也有列索引columns
-
可以被看做由Series组成的字典
创建dataframe最常用的方法,见02节读取纯文本文件、excel、mysql数据库
2.1根据多个字典序列创建dataframe
data = { 'state': ['ohio',' Ohio','0hio','Nevada', 'Nevada'], 'year': [2000,2001,2002,2001,2002], 'pop': [i.5,1.7,3.6,2.4,2.9], } # 转化为 DataFame对象 df = pd.DataFrame(data) # 与 Csv 操作一致 df.dtypes df.cloumns df.index
3从DataFrame 中 查询 Series
-
如果只查询一行、一列,返回的是pd.Series
-
如果查询多行、多列,返回的是pd.DataFrame
3.1查询一列,结果是一个pd.Series
df['year']
3.2查询多列,结果是一个pd.DataFrame
df[['vear', 'pop']] # 传入list
3.3查询一行,结果是一个pd.Series
df.loc[1]
3.4查询多行,结果是一个pd.DataFrame
# 列表的切片 # python 左闭右开 pandas 中 左闭右闭 df.loc[1:3]
三、查询数据
Pandas查询数据的几种方法
-
df.loc方法,根据行、列的标签值查询
-
df.iloc方法,根据行、列的数字位置查询
-
df.where方法
-
df.query方法
Pandas使用df.loc查询数据的方法
-
1.使用单个label值查询数据
-
2.使用值列表批量查询
-
3.使用数值区间进行范围查询
-
4.使用条件表达式查询
-
5.调用函数查询
注意
-
以上查询方法,既适用于行,也适用于列
-
注意观察降维dataFrame>Series>值
# 设定索引 方便查询 df.set_index('列名称', inplace=True) # 修改内容 df.lco[:, '列名称'] = df.['列名称'].str.replace("进行处理").astype('int32')
查询数据
1.使用lable单个查询
# 得到单个值 df.loc['索引值','列名称'] # 得到一个Series df.loc['索引值',['列名称1', '列名称2']]
2.使用值列表批量查询
# 得到Series df.loc[['索引1','索引2','索引3'],['列名称1', '列名称2']]
3.使用数值区间进行范围查询
# 列index按区同 df.loc['2018-01-03': '2018-01-05','bwendu'] df.loc['2018-01-o3', 'bWendu': 'fengxiang'] # 行和列都按区问查询 df.loc['2018-01-03': '2018-01-05','bWendu':'fengxiang']
4.使用条件表达式查询
# 条件查询 df.loc[df["ywendu"]<-10,:] # 复杂查询 #查询最高温度小于30度,并且最低温度大于15度,并且是晴天,并且天气为优的数据 df.loc[(df["bWendu"]<=30) & (df["yWendu"]>=15)& (df["tianqi"]=='晴') &(df["aqiLevel"]=l),:] print((df["bWendu"]<=30) & (df["yWendu"]>=15)& (df["tianqi"]=='晴') &(df["aqiLevel"]=l)) # 得到的值为 DataFrame 左侧为索引 右侧为 布尔值(是否满足筛选条件)
5.调用函数查询
# 直接使用lambda表达式 # 小匿名函数 df.loc[lambda df : (df["bwendu"]<=30)& (df["ywendu"]>=15),:] # 编写自己的两数,查询9月份,空气质量好的数据 def query_my_data(df): return df.index.str.startswith("2018-09") & df["aqiLevel"]==1 # 将函数当参数传入 df.loc[query_my_data,:]
AXIS
也许简单的来记就是axis=0代表往跨行(down),而axis=1代表跨列(across)
-
使用0值表示沿着每一列或行标签\索引值向下执行方法
-
使用1值表示沿着每一行或者列标签模向执行对应的方法
四、新增(修改)数据
在进行数据分析时,经常需要按照一定条件创建新的数据列,然后进行进一步分析。
-
直接赋值
-
df.apply方法
-
df.assign方法
-
按条件选择分组分别赋值
import pandas as pd fpath = "路径" df = pd.read_csv(fpath)
1.直接赋值法
# 替换掉温度的后缀℃ df.loc[:,"bWendu"] = df["bWendu"].str.replace("℃", "").astype('int32') df.loc[:,"yWendu"] = df["yWendu"].str.replace("℃", "").astype('int32') # 注意,df["bWendu"]其实是一个Series,后面的减法返回的是Series # 直接新增一列 df.loc[:,"wencha"] = df["bWendu"] - df["yWendu"]
2.df.apply方法
沿DataFrame的轴应用一个函数
传递给函数的对象是Series对象,其索引要么是DataFrame的索引(Axis=0),要么是DataFrame的列(Axis=1)。
# 实例:添加一列温度类型: # 1.如果最高温度大于33度就是高温 # 2.低于-10度是低温 # 3.否则是常温 def get_wendu_type(x): if x["bWendu"] >33: return '高温 if x["yWendu"] <-10: return '低温' return '常温' #注意需要设置axis==1,这是series的index是columns df.loc[:"wendu_type"] = df.apply(get_wendu_type,axis=1) # 查看温度类型的计数 # 对列中的每个值进行计数 df["wendu_type"].value_counts()
3.df.assign方法
将新列分配给DataFrame
返回一个新对象,该对象除新列外,还包含所有原始列。
# 可以同时添加多个新的列 df.assign( yWendi_huashi = lambda x : x["yWendu"] * 9/5 + 32, #摄氏度转华氏度 bWendu_huashi = lambda x : x["bWendu"] * 9/5 + 32
4、按条件选择分组分别赋值
# 先创建空列(这是第一种创建新列的方法) df['wencha_type'] = '' df.loc[df["bWendu"]-df["yWendu"]>10, "wencha_type"]= "温差大" df.loc[df["bWendu"]-df["yWendu"]<=10, "wencha_type"]="温差正常” df["wencha_type"].value_counts
五、统计函数
1.汇总类统计
# 一下子提取所有数字列统计结果 df.describe() # 计数,平均值,最大值,最小值,标准差std,分位数 df["列名"].mean() df["列名"].max() df["列名"].min()
2.唯一去重和按值计数
df["列名"].unique() # 查看总共包含哪些值 类似于set df["列名"].value_counts() # 查看每个值出现的次数 DataFrams
3.相关系数和协方差
用途(超级厉害)∶
1.两只股票,是不是同涨同跌?程度多大?正相关还是负相关? 2.产品销量的波动,跟哪些因素正相关、负相关,程度有多大?
对于两个变量X、Y:
1.协方差:衡量同向反向程度,如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;如果协方差为负,说明X,Y反向运动,协方差越小说明反向程度越高。 ⒉.相关系数:衡量相似度程度,当他们的相关系数为1时,说明两个变量变化时的正向相似度最大,当相关系数为- 1时,说明两个变量变化的反向相似度最大
# 协方差矩阵 列出各行各列 df.cov() # 相关系数矩阵 列出各行各列 df.corr() # 单独列出两列的协方差 df['列1'].cov('列2')
六、对缺失值的处理
Pandas使用这些函数来处理缺失值
isnull和notnull: 检测是否是空值,可用于df和series dropna:丢弃,删除缺失值 axis:删除行还是列,{0 or ‘index’,1 or ‘columns’},默认是0 how: 如果为any则任何值为空都删除,如果等于all,则所有的值为空的时候才进行删除操作 inplace: 为True则修改当前的df,否则返回新的df fillnal: 填充空值 value: 用于填充的值,可以是单个值,或者字典(key是列名,value是值) method: 等于ffill 使用前一个不为空的值填充forword fill; 等于bfill 使用后一个不为空的值填充back fill\ axis:按行还是列填充 {0 or ‘index’,1 or ‘columns’} inplace: 为True则修改当前的df,否则返回新的df
df.isnull() # 判断所有行列是否为空 返回布尔值 df['单个列'].isnull() # 对单个列操作 df.notnull() # 数据筛选 分数值是否非为空 返回布尔值 df['单个列'].notnull() # 对单个列操作 # 筛选所有非空行 df.loc[df['单个列'].notnull(),:] # 删除全是空的值的列 df.dropna(axis="columns", how="all", inplace=True) # 删除全是空值的行 df.dropna(axis="columns", how="all", inplace=True) # 将某列值改变 df.filna(["列名":"修改后的值"]) df.loc[:,"列名"] = df["列名"].fillna("修改后的值") studf.loc[:,"列名"] = df["列名"].fillna(method="ffill") # 保存excel # 不增添行索引 df.to_excel("路径", index=False)
小知识:
**SettingWithCopyWarning报警** Pandas 对DataFarms先 get 再 set 是错误的 不知道get 到的是 Copy(复制) 还是 View(原DataFarm直接操作) **解决方案** 1.先Copy 对 Copy后的 DataFrams 进行Set 2.直接进行Set
七、Pandas排序
Series的排序:
series.sort_values(ascending=True, inplace=False) **参数说明:**
-
ascending:默认为True升序排序,为False降序排序
-
inplace:是否修改原始Series
DataFrame的排序:
DataFrame.sort_values(by, ascending=True, inplace=False)
参数说明:
-
by:字符串或者List<字符串>,单列排序或者多列排序 默认为True升序排序,为False降序排序
-
ascending: bool或者List,升序还是降序,如果是list对应by的多列
-
inplace:是否修改原始DataFrame
# Series的排序 df["列名"].sort_values() # 逆序排序 df["列名"].sort_values(ascending=False) # 中文按照首字母逆序排序 # DataFrame的排序 # 根据 某列排序 # 对整行直接排序 df.sort_values(by="列名") # 逆序排列 降序 df.sort_values(by="列名",ascending=False) # 按照多列排序 af.sort_values(by=["列名","列名"]) # 分别指定多列排序的每列的 降序/升序 af.sort_values(by=["列名","列名"],ascending=[False,True])
八、字符串处理
前面我们已经使用了字符串的处理函数:
df["bWendu"].str.replace("℃","").astype('int32')
Pandas的字符串处理
-
使用方法:先获取Series的str属性,然后在属性上调用函数
-
只能在字符串列上使用,不能数字列上使用
-
Dataframe上没有str属性和处理方法
-
Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似
series.str字符串方法列表参考文档:
(https:/lpandas.pydata.org/pandas-docs/stable/reference/series.html#string-handling)
要求:
-
1.获取Series的str属性,然后使用各种字符串处理函数
-
2.使用str的startswith、contains等bool类Series可以做条件查询
-
3.需要多次str处理的链式操作
-
4.使用正则表达式的处理
# 获取Series 的 str属性 df['列名'].str # replace("被替换","替换为") df['列名'].str.replace("被替换","替换为") # 判断是否为数字 df['列名'].str.isnumeric # 查看字符长度 df['列名'].str.len() # 使用str的startswith、contains等得到bool的Series可以做条件查询 condition = df["列名"].str.startswith("2018-03") df(condition) # 需要多次str的链式操作 # slice 就是切片语法 df["列名"].str.replace("-","").str.slice(0,6) df["列名"].str.replace("-","").str[0:6] #### 正则表达式处理 # Series.str 默认开启了正则表达式模式 # 将 年/月/日 替换为 空字符串 df["中文日期"].srt.replace("[年月日]","")
九、axis参数
axis=0或者"index" :
-
如果是单行操作,就指的是某一行
-
如果是聚合操作,指的是跨行cross rows
axis=1或者"columns":
-
如果是单列操作,就指的是某一列
-
如果是聚合操作,指的是跨列cross columns
按哪个axis,就是这个axis要动起来(类似被or遍历),其它的axis保持不动
# 单行/列操作 # 删除某列 df.drop("A", axis=1) # 删除某行 df.frop(1, axis=0) # 指定了按哪个axis,就是这个axis要动起来(类似被for遍历),其它的axis保持不动 # 多行/列操作 # 跨行操作 输出列结果 df.mean(axis=0) # 跨列操作 输出行结果 df.mean(axis=1)
十、index的用途
用途总结
-
1.更方便的数据查询;
-
2.使用index可以获得性能提升;
-
3.自动的数据对齐功能;
-
4.更多更强大的数据结构支持;
# 设置index 为某列的数据 df.set_index("列名称", inplace=True, drop=False) # 可以简化写法 df.loc[500].head() df.loc[df["userId"] == 500].head()
使用index提升查询性能
-
·如果index是唯一的,Pandas会使用哈希表优化,查询性能为O(1);
-
·如果index不是唯一的,但是有序,Pandas会使用二分查找算法,查询性能为O(IogN);
-
·如果index是完全随机的,那么每次查询都要扫描全表,查询性能为O(N);
# index 属性 df.index.is_monotonic_increasing # 判断index是否为单调递增 df.index.is_unique # 计时 %time df.loc[500] # 计算查询 500index 的性能
index自动对齐数据
# 创建Series s1 = pd.Series([1,2,3], index=list("abc")) s2 = pd.Series([2,3,4], index=list("abc")) s1 + s2 # 1 与 4 是空 因为没有对应 index数据 # 2 与 3 是两列 2 3 的和
4.使用index更多更强大的数据结构支持
很多强大的索引数据结构
-
Categoricallndex,基于分类数据的Index,提升性能;
-
Multilndex,多维式用于groupby多维聚合后结果等;
-
Datetimelndex,时间类型索引,强大的日期和时间的方法支持;
十一,合并表格
1.concat
df = pd.concat(objs, axis = 0, ignore_index = False, join = "outer")
concat是”contatenate"的缩写,指的是多表之间的“拼接”。其实“拼接”和“合并”还是有区别的,后面我们会说到。事实上,concat方法有很多参数,上例给出的只是常用的。其中:
-
objs: 指的是要合并的dataframe(们)。可以是一个列表[df1,df2,...]也可以是一个集合(df1,df2,...)。(我是这么理解的,试了一下列表集合都有效)
-
axis:指的是拼接的方向。axis = 0指的是拼接行(向下拼接),axis = 1指的是拼接列(向右拼接)。
-
ignore_index: 指的是拼接后是否忽视原df各自的索引。比如,假如我们按行拼接,原来df1中有五条数据,索引是0,1,2,3,4。原来的df2中也有五条数据,索引也是0,1,2,3,4。如果我们在合并时,将ignoreindex的值设为False,那么拼接后df的索引就是0,1,2,3,4,0,1,2,3,4。那么如果将ignore_index的值设为True, 那么拼接后df的索引就是0,1,2,3,4,5,6,7...
-
join:表示“如何拼接”。由于两表中的信息可能是不同的,所以要设置这个参数以表明拼接方式。其中,outer表示取并集,inner表示取交集。
2.Merge
用于合并表格
merge的语法:
pd.merge(left, right,how=inner , on=None, left_on=None,right_on=None, left_index=False,right_index=False, sort=Tue,sikes=('_X' '_y'), copy=True.indicator=False, validate=None)
-
left,right:要merge的dataframe或者有name的Series-
-
how: join类型,"left, "right", 'outer , " inner'
-
on: join的key,let和right都需要有这个key.
-
left_on: left的df或者series的key
-
left_index, right_index:使用index而不是普通的column做join
-
right_on: pight的df或者seires的key
-
ssuffixes:两个元素的后缀,如果列有重名,自动添加后缀,默认是(X,'y')