Pandas介绍与安装
为什么会有Pandas?
Pandas支持大部分Numpy语言风格,尤其是数组函数与广播机制的各种数据处理。但是Numpy更适合处理同质型的数据。而Pandas的设计就是用来处理表格型或异质型数据的,高效的清洗、处理数据。
Pandas是什么?
Pandas是基于Numpy的一种工具,提供了高性能矩阵的运算,该工具是为了解决数据分析任务而创建的。也是贯穿整个Python数据分析非常核心的工具。
Pandas涉及内容
Pandas安装
直接在dos命令行中pip install pandas 即可。
Pandas基础数据结构
series
Series介绍
Series是一种一维的数组型对象,它包含了一个值序列(values),并且包含了数据标签,称为索引(index)。
Series创建
pd.Series(data=None,index=None,dtype=None,name=None,copy=False)
- data:创建数组的数据,可为array-- --like, dict, or scalar value
- index:指定索引
- dtype:数组数据类型
- name:数组名称
- copy:是否拷贝
data可为iterable, dict, or scalar value
import pandas as pd
pd.Series([1,2,3,4,5,6]) # data为iterable
索引默认为range(0,n) 可以通过index指定索引
pd.Series([1,2,3,4,5]),index=list("abcde"))
数据类型根据data自动调整,但是也可以通过dtype指定
pd.Series(np.random.randint(1,10,size=5),dtype="float")
使用name参数设置数组名称
pd.Series(np.random.randint(1,10,size=3),index=list("abc"),name="data_name")
除此之外,Pandas可以使用Numpy的数组函数。
- s.dtype # 查看数据类型
- s.astype() # 修改数据类型
- s.head(n) # 预览数据前5条
- s.tail(n) # 预览数据后五条
但是如果需要显示所有数据,则需以下代码。但并不建议使用
# 显示所有列
pd.set_option('display.max_columns',None)
# 显示所有行
pd.set_option('display.max_rows',None)
#设置value的显示长度为100,默认50
pd.set_option('max_colwidth',100)
series的索引与值
- s.index # 查看索引
- s.values # 查看值的序列
- s.reset_index(drop=False) # 重置索引
- drop # 是否删除原索引 默认为否
注意
- 索引对象是不可变的,所以不能单个修改索引
Series索引与切片
- s[‘标签’] # 通过标签
- s[‘索引’] # 通过索引
- s.loc(标签) # 通过标签
- s.iloc(索引) # 通过索引
Series运算
- 共同索引对应为运算,其他填充NaN
S1 = pd.Series(range(10,20),index=range(10))
s2 = pd.Series(range(20,25),index=range(5))
s1+s2
- 没有共同索引时,则全部为NaN
DataFrame
DataFrame介绍
DataFrame介绍表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值,字符串,布尔值)。在DataFrame中,数据被存储为一个以上的二维块。
DataFrame创建
pd.DataFrame(data=None,index=None,columns=None,dtype=None,copy=False)
- data:创建数组的数据,可为ndarray,dict
- index:创建索引
- dtype:数组数据类型
- copy:是否拷贝
重置索引
除了创建时可以指定,我们创建后还可以通过df.reindex()进行重置索引。
- df.reindex(index=None,columns=None,axis=None,fill_value=NaN)
DataFrame基础操作
- df.shape # 查看数组情况,返回值为元祖
- df.dtypes # 查看列数据类型
- df.ndim # 数据维度,返回为整数
- df.index # 行索引
- df.columns # 列索引
- df.values # 值
- df.head(n) # 显示头部几行,默认前5行
- df.tail(n) # 显示末尾几行,默认后5行
- df.info() # 相关信息概述
data = [
{"name":"amy","age":18,"tel":10086},
{"name":"bob","age":18},
{"name":"james","tel":10086},
{"name":"zs","tel":10086},
{"name":"james","tel":10086},
{"name":"ls","tel":10086},
]
d2 = pd.DataFrame(data)
d2.head()
d2.tail()
d2.info()
DataFrame查数据(索引与切片)
直接使用索引与标签:
类型 | 描述 |
---|---|
df[:索引]或df[:“标签”] | 表示对行操作 |
df[“列标签”]或df[[“列标签”,“列标签”]] | 表示对列进行操作 |
练习1 | |
读取文件catNames2.csv |
- 取前两行
- 取出Count_AnimalName列
- 取出Row_Labels前两行
练习2
找到所有的使用次数超过800的猫的名字
使用loc及iloc查询数据: - df.loc[] 通过轴标签选择数据
- df.iloc[] 通过整数索引选择数据
具体使用如下
类型 | 描述 |
---|---|
df.loc[val] | 根据标签索引选择DataFrame的单行或多行 |
df.loc[:,val] | 根据标签索引选择DataFrame的单列或多列 |
df.loc[val1,val2] | 同时选择行和列中的一部分 |
df.iloc[where] | 根据位置索引选择DataFrame的单行或多行 |
df.iloc[:,where] | 根据位置索引选择DataFrame的单列或多列 |
df.iloc[where_i,where_j] | 根据位置索引选择行和列 |
注意: | |
df[val1:val2] 不加loc或iloc时 val1代表列;val2代表行,反之则val1代表行;val2代表列。 | |
例如:df[[1,2]:[1,2]] |
DataFrame修改数据
修改数据主要遵循以下两点:
- 查询数据
- 再赋值
注意
Pandas中可以直赋值np.NaN,且赋值当前列数据会自动转为浮点类型。而不是整个数组都转,这主要是因为Pandas数据可以是异质性。
DataFrame新增数据
新增列: df[“新的列标签”] = 值
注意:添加列,则新添加的值的长度必须与其它列的长度保持一致,否则会报错。
插入列: 如果需要在数据中心插入列,则使用 df.insert(loc,column,value)
- loc 为插入列的位置
- columns 为插入列的标签
- value 为插入列的值
添加行: df.loc[“新的行标签”,:] = 值
除此之外,我们还可以通过df.append(df2)
方法添加行,但类似于数组与数组的堆叠拼接。所以df2的列索引必须同df一致。
DataFrame删除数据
方法1:del df[“列标签”]
方法2:df.drop(axis =0,index =None,columns =None,inplace =False)
DataFrame算术
实际上,通过+ - * / // **
等符号可以直接对DataFrame与DataFrame之间或者DataFrame以及Series之间进行运算。但秉承的原则是对应索引运算,存在索引不同时,返回结果为索引对的并集
使用填充值的算术方法
方法 | 描述 |
---|---|
add,radd | 加法(+) |
sub,rsub | 减法(-) |
div,rdiv | 除法(/) |
floordiv,rfloordiv | 整除(//) |
mul,rmul | 乘法(*) |
pow,rpow | 幂次方(**) |
注意
- Series使用算术方法,不支持指定填充值
描述性统计的概述和计算
方法 | 描述 |
---|---|
count | 非NA值的个数 |
min,max | 最小值,最大值 |
idxmin,idxmax | 最小值,最大值的标签索引 |
sum | 求和 |
mean | 平均值 |
median | 中位数 |
var | 方差 |
std | 标准差 |
cumsum | 累计值 |
cummin,cummax | 累计值的最小值或最大值 |
cumprod | 值的累计积 |
diff | 计算第一个算术差值(时间序列) |
pct_change | 百分比 |
corr | 按索引对其的值的相关性 |
cov | 协方差 |
DataFrame排序 |
- df.sort_index(axis=0,ascending=True) # 索引排序
- axis指定轴,默认为0轴
- ascending为排序方式,默认为True表示升序
- df.sort_values(by) # 值排序
- by指定一列或多列作为排序键
注意
- by指定一列或多列作为排序键
- by = [col1,col2] 是先给col1排序,当col11有相同值时,col2中安排续顺序再排序
练习
关于猫的名字的统计数据,获取用次数最高的名字
函数应用于映射 - df.apply(func,axis=0) # 通过apply将函数运用到列或者行
- df.applymap(func) # applymap将函数应用到每个数据上
数据读取存储
csv文件
- 读取csv文件
read_csv
(file_path or buf,usecols,encoding)
file_path
:文件路径
usecols
:指定读取的列名
encoding
:编码
data = pd.read_csv('d:/test_data/food_rank.csv',encoding='utf8')
data.head()
name num
0 酥油茶 219.0
1 青稞酒 95.0
2 酸奶 62.0
3 糌粑 16.0
4 琵琶肉 2.0
#指定读取的列名
data = pd.read_csv('d:/test_data/food_rank.csv',usecols=['name'])
data.head()
name
0 酥油茶
1 青稞酒
2 酸奶
3 糌粑
4 琵琶肉
#如果文件路径有中文,则需要知道参数engine='python'
data = pd.read_csv('d:/数据/food_rank.csv',engine='python',encoding='utf8')
data.head()
name num
0 酥油茶 219.0
1 青稞酒 95.0
2 酸奶 62.0
3 糌粑 16.0
4 琵琶肉 2.0
#建议文件路径和文件名,不要出现中文
- 写入csv文件
DataFrame:to_csv
(file_path or buf,sep,columns,header,index,na_rep,mode)
file_path
:保存文件路径,默认None
sep
:分隔符,默认’,’
columns
:是否保留某列数据,默认None
header
:是否保留列名,默认True
index
:是否保留行索引,默认True
np_rep
:指定字符串来代替空值,默认是空字符
mode
:默认‘w’,追加‘a’
**Series**:`Series.to_csv`\(_path=None_,_index=True_,_sep='_,_'_,_na\_rep=''_,_header=False_,_mode='w'_,_encoding=None_\)
数据库交互
- pandas
- sqlalchemy
- pymysql
# 导入必要模块
import pandas as pd
from sqlalchemy import create_engine
# 初始化数据库连接
# 用户名root 密码 3306 数据库db2
engine = creat_engine('mysql+pymysql://root:@localhost:3306/db2')
# 查询语句
sql = '''
select * from class;
'''
# 两个参数 sql语句 数据库连接
df = pd.read_sql(sql,engine)
df
# 新建
df = pd.DataFrame({'id':[1,2,3,4],'num':[34,56,78,90]})
df = pd.read_csv('ex1.csv')
# 写入到数据库
df.to_sql('df2',engine,index=False)
print("ok")
进数据库查看:
Pandas数据清洗
数据清洗介绍
数据清洗实际上也是数据质量分析,检查原始数据中是否存在脏数据(不符合要求,或者不能直接进行分析的数据),并且处理脏数据。
常见情况如下
- 缺失值
- 异常值
- 重复数据
处理缺失值
Pandas使用浮点值NaN(Not a Number)表示缺失值,并且缺失值在数据中时常出现。那么Pandas的目的之一就是**“无痛的”**处理缺失值。
判断数据是否为NaN
- pd.isnull(df) 返回哪些值是缺失值的布尔值
- pd.notnull(df) 返回值时isnull的反集
注意 - Python内建的None值也被当做NaN
过滤缺失值 - dropna(axis=0,how=‘any’,inplace=False)
- axis 指定轴 默认为0 代表行
- how 默认为any 代表删除含有NaN的行 当为all时代表删除所有值为NaN的行
- inplace 修改被调用的对象 而不是一个备份(不用再赋值了,直接使用)
- inplace=False,默认该删除操作不改变原数据,而是返回一个执行删除操作后的新dataframe;
- inplace=True,则会直接在原数据上进行删除操作,删除后无法返回。
pandas—删除某行或某列数据
# 创建一个DataFrame格式数据
data = {'a': ['a0', 'a1', 'a2'],
'b': ['b0', 'b1', 'b2'],
'c': [i for i in range(3)],
'd': 4}
df = pd.DataFrame(data)
print('举例数据情况:\n', df)
注:DataFrame是最常用的pandas对象,使用pandas读取数据文件后,数据就以DataFrame数据结构存储在内存中。
pandas数据行列删除,主要用到drop()和del函数,用法如下:
drop()
- DataFrame.drop(labels,axis=0,level=None,inplace=False,errors=’raise’)
- labels 接收string或array,代表要删除的行或列的标签(行名或列名)。无默认值
- axis 接收0或1,代表操作的轴(行或列)。默认为0,代表行;1为列。
- level 接收int或索引名,代表标签所在级别。默认为None
- inplace 接收布尔值,代表操作是否对原数据生效,默认为False
- errors errors='raise’会让程序在labels接收到没有的行名或者列名时抛出错误导致程序停止运行,errors='ignore’会忽略没有的行名或者列名,只对存在的行名或者列名进行操作。默认为‘errors=‘raise’’。
实例1:删除d列
df1 = df.drop(labels='d', axis=1)
print('删除d列前:\n', df)
print('删除d列后:\n', df1)
实例2:删除第一行
df2 = df.drop(labels=0)
print('删除前:\n', df)
print('删除列:\n', df2)
实例3:同时删除多行多列
df3 = df.drop(labels=['a', 'b'], axis=1) # 同时删除a,b列
df4 = df.drop(labels=range(2)) # 等价于df.drop(labels=[0,1])
print('删除前:\n', df)
print('删除多列(a,b):\n', df3)
print('删除多行(第1,2行):\n', df4)
df5 = df[df['c'] < 2]
df6 = df.drop(labels=range(2)) # 同时删除c列小于2的行
print('删除前:\n', df)
print('删除多行(c列小于2):\n', df6)
注意:(1)、删除列的操作时,axis参数不可省,因为axis默认为0(行);
(2)、没有加入inplace参数,默认不会对原来数据进行修改,需要将结果赋值给新的变量。
del
语法:del df[‘列名’]
此操作会对原数据df进行删除,且一次只能删除一列。
正确用法
del df['d']
print('原地删除d列后:\n', df)
错误用法:
del df[['a', 'b']]
print(df)
- drop()相对于del()来说,灵活性更高,更为实用。
补全缺失值(NaN)
- df.fillna(value=None,method=None,axis=None,inplace=False,limit=None)
- value 标量或字典对象用于填充缺失值
- method 插值方法 默认为“ffill”
- axis 需填充的轴 默认为0
- inplace 修改被调用的对象 而不是一个备份
- limit 用于向前或向后填充时最大的填充范围
异常值
脏数据也包含不符合要求的数据,name对这块数据处理不能直接使用fillna填充。使用replace更加灵活。
- df.replace(to_replace=None,value=None)
- to_replace 去替换的值
- value 替换的值
处理重复数据
判断重复值
- df.duplicated(subset=None,keep=‘first’) 返回一个布尔值Series,默认反应的是每一行是否与之前出现过的行相同
- subset 指定子列判断重复
- keep 默认为first保留首个出现的 last保留最后出现的
删除重复值
- df.drop_duplicates(subset=None,keep=‘first’) 返回的是DataFrame 默认删除重复行
- subset 指定子列判断重复
- keep 默认为first保留首个出现的 last保留最后出现的
练习1
IMDB-Movie-Data.csv
根据给定数据绘制电影市场分布
练习2
读取FoodFacts.csv
文件,对全球每个国家添加剂的使用进行分析。
离散化
离散化是把无限空间中有限的个体映射到有限的空间中去,以此提高算法的时空效率。可以简单的理解为离散化就是将连续值进行分区间。
- pd.cut(x,bins) 将连续数据x进行离散化
- x 要进行离散化的数据
- bins 分组
- pd.value_counts(cates) 统计每个区间的数值分布
利用映射转换数据
需求:如下数据。进行分班
- 一班:胡歌,小岳岳,林更新
- 二班:金世佳,郭麒麟
data = {
"names":["胡歌","金世佳","林更新","郭麒麟","小岳岳"],
"grades":np.random.randint(1,100,size=5)
}
df = pd.DataFrame(data)
使用:df[“列标签”].map(“映射到的数据”)
重命名轴索引
需求:如下数据,将行索引名字全部转为大写
data = {
"names":["bob","amy","cheney","jerry"]
"grades":np.random.randint(60,100,size=4)
}
df2 = pd.DataFrame(np.random.randint(60,100,size=(4,2)),index=["bob","amy","cheney","jerry"])
df2
方法一:
- 使用map函数映射
df.index.map(str.upper)
- df.index.map(lambda x : x.upper)
- columns同理
方法二:(推荐)
- 使用df.rename 方法
df.rename(index,columns)
- rename方法一:df.rename(index = str.lower,columns = str.upper)
- rename方法二:df.rename(index = {“A”:“B”} , columns ={})
- dict中的键值对必须一一对应
- A是修改之前的名称 B是要修改的名称
向量化字符串函数
练习:读取 catNames2.csv
,找到所有的使用次数超过700并且名字的字符串的长度大于4的动物的名字
计算虚拟变量
将分类变量转换为"虚拟"或"指标"矩阵是另一种用于统计建模或机器学习的转换操作。如果DataFrame中的一列有K个不同的值,则可以衍生出一个K列的值为1和0的矩阵或DataFrame。
- pd.get_dummies() 将分类变量转换为"虚拟"或"指标"矩阵
但是,如果说DataFrame中的一行属于多个类别,情况就会比较复杂。如下图
练习
读取IMDB-Movie-Data.csv对其分类(Genre)这列转化为虚拟矩阵。
数据规整
索引与分层索引
索引
- 查看索引:df.index
- 指定索引:df.index = [,] 个数必须一致
- 重新索引:df.reindex([,]) 无需个数一致,多出的会用NaN填充
- 指定某一列作为index:df.set_index(“M”,drop=False)
- 返回index的唯一值:df.set_insex(“M”).index.unique()
- 重置索引: df.reset_index(inplace=True,drop=True)
- inplace=False,默认该删除操作不改变原数据,而是返回一个执行删除操作后的新dataframe;
- inplace=True,则会直接在原数据上进行删除操作,删除后无法返回。
- drop=True就是把原来的索引index列去掉,重置index;
- drop=False就是保留原来的索引,添加重置的index。
分层索引
分层索引是Pandas一个重要的特性,允许在一个轴上拥有多个索引层级。
df = pd.DataFrame({
'a':range(7),
'b':range(7,0,-1),
'c':['one','one','one','two','two','two','two'],
'd':list("hjklmno")
})
df.set_index(["c","d"])
Pandas从多个条件(AND,OR,NOT)中提取数据
使用Pandas从多个条件(AND,OR,NOT)中提取行的方法。
有以下2点需要注意:
- &,|,〜的使用(and、or、not的错误)
- 使用比较运算符时,请将每个条件括在括号中。
df_and = df[(df['age'] < 35) & ~(df['state'] == 'NY')]
- 运算符的优先级是NOT(〜),AND(&),OR(|)。因此,结果因顺序而异。
数据合并
数据合并也就是说将多个数据集拼接在一起,但是合并的方式主要分为:pandas.merge,pandas.concat,df.join。以下,我们来详细的介绍。
merge()
基于列进行关联,是最常用的一种方法。函数为:
pd.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False)
- left:拼接左侧的DataFrame对象;
- right:拼接右侧的DataFrame对象;
- on:待关联的同名列名,存在于左右两个DataFrame对象中;
- how:连接方式,inner(默认),其他可选:outer、left、right;
- left_on:左侧DataFrame中用作连接键的列名;
- right_on:右侧DataFrame中用作连接键的列;
- left_index:将左侧的行索引用作其连接键;
- right_index:将右侧的行索引用作其连接键;
"""
创建数组1
"""
polls = {"sites":["迈皋桥", "草场门", "浦口", "奥体中心", "仙林大学城"],
"AQI":[55, 75, 69, 74, 58],
"PM25":[30, 54, 47,40 ,27],
"SO2":[10, 15, 13, 17, 10]}
sites = {"names":["迈皋桥", "草场门", "浦口", "奥体中心", "玄武湖"],
"regions":["栖霞区", "鼓楼区", "浦口区", "建邺区", "玄武区"],
"weather":["晴", "晴", "多云", "阴", "晴"]}
# 读取数据集,把字典格式转变为DataFrame格式
df_polls = pd.DataFrame(polls)
df_sites = pd.DataFrame(sites)
"""
创建数组2
"""
# 定义左侧数据集
df_left = pd.DataFrame({"sites":["迈皋桥", "草场门", "浦口", "迈皋桥", "草场门", "浦口"],
"date":["2020-12-08", "2020-12-08", "2020-12-08", "2020-12-07", "2020-12-07", "2020-12-07"],
"AQI":[55, 75, 69, 45, 35, 53]})
# 定义右侧数据集
df_right = pd.DataFrame({"sites":["迈皋桥", "草场门", "迈皋桥", "草场门"],
"date":["2020-12-08", "2020-12-08", "2020-12-09", "2020-12-09"],
"weather":["晴", "晴", "多云", "阴"]})
"""
创建数组3
"""
sites_with_index = pd.DataFrame({"regions":["栖霞区", "鼓楼区", "浦口区", "建邺区", "玄武区"]},
index=["迈皋桥", "草场门", "浦口", "奥体中心", "玄武湖"])
join()
join方法是基于index连接DataFrame。join连接方法有内连接,外连接,左连接和右连接,与merge一致。
"""
创建数组4
"""
polls_with_index = pd.DataFrame({"AQI":[55, 75, 69, 74, 58],
"PM25":[30, 54, 47,40 ,27],
"SO2":[10, 15, 13, 17, 10]},
index=["迈皋桥", "草场门", "浦口", "奥体中心", "仙林大学城"])
concat()
另外一种常用的数据整合方法是concat,即我希望按照某找方式把两个规整的数据集进行拼接。拼接原型函数非常简单:
pd.concat(objs,axis=0,join='outer',keys=None)
- objs:带拼接的数据集,通常以列表的形式传入;
- join:可选inner、outer,含义同merge函数;
- keys:定义新的分组索引,用来区分传入的数据集
"""
创建数组5
"""
new_polls = {"sites":["迈皋桥", "草场门", "浦口", "奥体中心", "仙林大学城"],
"AQI":[65, 85, 79, 78, 78],
"PM25":[50, 74, 67,60 ,47],
"O2":[20, 35, 23, 37, 15]}
df_polls_new = pd.DataFrame(new_polls)
数据分组与聚合
数据包含在Series、DataFrame数据结构中,可以根据一个或多个键分离到各个组中。分组操作之后,一个函数就可以应用到各个组中,产生新的值。如下图则是简单的分组聚合过程。
key为指定分组的列
- df.groupby(‘key’)
import pandas as pd
import numpy as np
df1 = pd.DataFrame(
{
"names":["菲菲","小可爱","mia","牛哥","老王","mia","狼人","药水哥","药水哥"],
"classes":["一班","二班","三班"]*3,
"grades":np.random.randint(60,100,size=9)
}
)
df1
df1.groupby(by="classes")["grades"].mean()
groupy求取分组的个数
df1.groupby(by="classes").size()
聚合函数如下:
自定义聚合函数
实现步骤:
- 自定义函数
- 分组后通过agg或者aggregate进行聚合
def classes_ptp(x):
return x.max()-x.min()
df1.groupby(by="classes")["grades"].age(classes_ptp)
df1.group(by="classes")["grades"].aggregate(classes_ptp)
分组块上应用函数
实现步骤:
- 定义函数
- 通过apply方法将函数应用到分组后的数组
def sort_df(df):
return df.sort_values(by="grades")
df1.groupby(by="classes").apply(sort_df)
除了以上分组形式,还可以通过字典、series、函数进行分组
df2 = pd.DataFrame(
np.random.randint(60,100,size=(5,3)),
index=["菲菲","小可爱","mia","牛哥","老王"],
columns=["语文","数学","英语"]
)
df2
pd按照某一列进行排序
- pandas按照某一列进行排序,sort_values表示根据某一列排序 pd.sort_values(“xxx”,inplace=True) 表示pd按照xxx这个字段排序,inplace默认为False,如果该值为False,那么原来的pd顺序没变
data1 = pd.Series(np.random.randint(1,10,size = 5))
data1.sort_values()
data2 = pd.DataFrame({'ID':np.random.randint(1,10,size = 5),'AGE':np.random.randint(1,10,size = 5)})
data2.sort_values('ID',inplace=True)
- pandas按照索引进行排序,sort_index。
data1 = pd.Series(np.random.randint(1,10,size = 5))
data1.sort_index()
data2 = pd.DataFrame({'ID':np.random.randint(1,10,size = 5),'AGE':np.random.randint(1,10,size = 5)})
data2.sort_index()
sort_value排序
df.sort_values(by='xxx', axis=0, ascending=True, inplace=False,kind='quicksort', na_position='last', ignore_index=False, key=None)
参数:
- by – 指定列名(axis=0或者’index’)或索引值(axis=1者’columns’)
- axis – 按行、按列,默认axis=0按指定列排序
- ascending – 是否升序 默认为True
- inplace – 是否修改原对象
- kind – 排序算法 快排quicksort、归并mergesort、堆排序
- heapsort、稳定排序stable,默认快排
- na_position – {‘first’, ‘last’} 设定缺失值的显示位置
- ignore_index – 排序后是否重置索引
- key – 排序之前使用的函数 (version 1.1.0 后才有该参数)
时间序列
时间序列前言
时间序列数据在很多领域都是重要的结构化数据形式,比如:金融,神经科学,生态学,物理学。在多个时间点观测的数据形成了时间序列。时间序列可以是固定频率的,也可以是不规则的。
常见使用
- 时间戳
- 固定的时间区间
- 时间间隔
时间序列基础
时间序列介绍
Pandas中的基础时间序列种类是由时间戳索引的Series,在Pandas外部通常表示为Python字符串或datatime对象。
注意
- datetime对象可作为索引,时间序列DatetimeIndex
- <M8[ns]类型为纳秒级时间戳
- 时间序列里面每个元素为Timestamp对象
生成时间序列函数
- pd.date_range(start=None,end=None,periods=None,freq=None,tz=None,normalize=False)
- start 起始时间
- end 结束时间
- periods 固定时期
- freq 日期偏移量(频率)
- normalize 标准化为0的时间戳
d1 = pd.date_range(start="20200101",end="20200201")
d1
d2 = pd.date_range(start="20200101",end="20200201",periods=5)
d2
d3 = pd.date_range(start="20200101",periods=5,freq="10D")
d3
d4 = pd.date_range(start="2020-01-01 12:59:59",periods=5,freq="10D",normalize=True)
d4
关于频率设置如下:
具体可参考:https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timeseries-offset-aliases
时间序列的索引及选择数据
ts = pd.Series(np.random.randint(1,100,size=800),index=pd.data_range("20180101",periods=800))
ts
# 选择2020的数据
ts['2020']
# 选择2020的一月份数据
ts['2020 01']
# 取2020年5月01至5月10的数据
ts['2020 05 01':'2020 05 10']
含有重复索引的时间序列
- df.indexis_unique 检查索引是否唯一
移位日期
“移位”指的是将日期按时间向前移动或向后移动。Series和DataFrame都有一个shift方法用于进行简单的前向或后向移位,而不改变索引
ts.shift(2) # 向前移动
ts.shift(-2) # 向后移动
重采样
重采样介绍
重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样
ts = pd.DataFrame(np.random.randint(100,200,size=100),index=pd.data_range(start="20200101",periods=100))
ts
ts.resample("M").mean()
以上为时间序列的基本内容。但是我们来看以下常见场景
df = pd.DataFrame(np.random.randint(1000,4000,size=(4,4)),index=[20200101,20200102,20200103,20200104],columns=["北京","上海","广州","深圳"])
df
转换为时间索引
该行索引类型并不是时间序列类型,所以我们想要使用时间序列的特性,就需要将其转为时间序列。通过pd.to_datetime()
,其中的format参数可以调试时间序列的格式,常用如下:
时间索引提取年月日
import pandas as pd
list_of_dates = ['2019-11-20', '2020-01-02', '2020-02-05','2020-03-10','2020-04-16']
employees=['Hisila', 'Shristi','Zeppy','Alina','Jerry']
df = pd.DataFrame({'Joined date': pd.to_datetime(list_of_dates)}, index=employees)
df['Year'] = df['Joined date'].dt.year
df['Month'] = df['Joined date'].dt.month
df['Day'] = df['Joined date'].dt.day
# 转化为日期类型datetime64[ns]
df['Date'] = pd.to_datetime(df['Joined date'].dt.date)
print(df)
pd_to_datetime将时间戳转换日期格式问题
一、问题描述
data["date"] = pd.to_datetime(data["timestamp"],unit = "ms")
将时间戳数据转换成日期格式,使用的是pd_to_datetime进行转换,转化后 出现了不一致性,比真实时间少8小时。
二、原因分析
- 查看pd_to_datetime文档,发现有一个utc的字段,来控制时区导致的
三、解决方式
df['time'] = pd.to_datetime(df['timestamp'], unit='ms') + pd.Timedelta(hours=8)
练习
统计出911数据中不同月份的电话次数
练习
北上广深与沈阳5个城市空气质量数据,绘制出北京的PM2.5随时间的变化情况
常遇问题集
问题1
如下图,没有显示删除后的数据。
原因1
这是因为 df.dropna()
在没有指定 inplace=True
的时候他是不改变原有数据的,也就是说实际上df并没有改变。
那此处的代码就是因为,没有改变df10本身,所以输出df10是没有任何变化的。
问题2
向量化字符串函数只适用于Series对象,而不适用于DataFrame奥~
注意:而且只能用于字符串,如果是数值要进行处理,则可使用apply进行应用
问题3
df_f = pd.DataFrame({
'a':range(7),
'b':range(7,0,-1),
'c':['one','one','one','two','two','two','three'],
'd':list("hjklmno")
})
df_f4 = df_f.set_index(["c","d"])
'''
a b
c d
one h 0 7
j 1 6
k 2 5
two l 3 4
m 4 3
n 5 2
three o 6 1
'''
# 取one,two两块
#print(df_f4.loc["one":"two"])
# 报错:pandas.errors.UnsortedIndexError: 'Key length (1) was greater than MultiIndex lexsort depth (0)'
#但用神奇索引可以正常取值
print(df_f4.loc[["one","two"]])
'''
c d
one h 0 7
j 1 6
k 2 5
two l 3 4
m 4 3
n 5 2
上课讲解时,只有 one,two 两块,所以使用 df_f4.loc[“one”:“two”] 获取数据时,没有问题。但是当添加一个 three 时候就会报错。
原因3
问题就在索引无序,而切片等操作要求有序。
解决这问题可用pd.sort_index()的方法来先给索引排序。之后就可切片。