python,pandas_python常用的科学计算库

python,pandas_python常用的科学计算库[python][科学计算][pandas]使用指南

大家好,又见面了,我是你们的朋友全栈君。

最后一次更新日期: 2019/5/26

新增字符串和时间处理的简要介绍
缺失值填充、删除、读写excel小节做了少许补充

pandas是基于numpy的数据分析库,提供一些更易用的数据模型和大量高效的统计方法。

使用前先导入模块:

import pandas as pd

按需导入以下模块:

import numpy as np

import matplotlib.pyplot as plt

点击下方链接可前往各小节

使用指南1 – 数据模型与属性 (索引,数据序列,数据框,分类数据)

使用指南2 – 数据类型与转换 (数据类型,类型转换)

使用指南3 – 数组与统计运算 (运算符和标量值函数,统计方法,自定义函数,广播)

使用指南4 – 查询与关联 (索引查找,表连接)

使用指南5 – 增删改 (更新,增加,删除,重构索引,行列转置,缺失值填充)

使用指南6 – 排序与去重 (直接与间接排序,去重)

使用指南7 – 乱序与抽样 (随机排序,抽样)

使用指南8 – 读写 (读写csv,读写excel,读写sql)

使用指南9 – 快速绘图 (曲线图,条形图,直方图,箱线图,散点图,饼图)

使用指南10 – 特殊类型处理 (字符串,时间)

一. 数据模型与属性

返回目录

1. 索引Index

numpy中只有位置索引,而pandas还增加了标签索引,依赖于一个专用的Index类型。

常规索引

pd.Index([1,2,3])
Out[64]: Int64Index([1, 2, 3], dtype='int64')

pd.Index([1.,2.,3.])
Out[65]: Float64Index([1.0, 2.0, 3.0], dtype='float64')

pd.Index(['a','b','c'])
Out[66]: Index(['a', 'b', 'c'], dtype='object')

pd.Index(range(10))
Out[67]: RangeIndex(start=0, stop=10, step=1)

pd.Index(range(10)).values
Out[68]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64)

import datetime as dt
dt1=dt.datetime.now()
dt2=dt1+dt.timedelta(days=1)

pd.Index([dt1,dt2])
Out[81]: DatetimeIndex(['2019-03-09 20:56:14.644159', '2019-03-10 20:56:14.644159'], dtype='datetime64[ns]', freq=None)
复制代码

Index在创建时会根据传入数据(一维序列)自动生成具体的索引类型,也可通过dtype参数指定类型,但无法正常转换时会报错;copy参数指定创建索引时是否复制源数据,默认false。 具体的索引类型也可通过各自的方法创建。 Index.values可以查看作为数据基础的一维数组,Index.dtype可以查看数据类型。

多级索引

pandas提供了多级索引以便于分组数据,可用于构造高维数据集,groupby计算也会自动产生多级索引。

midx=pd.MultiIndex(levels=[['a','b'],['c','d']],labels=[[1,1,0,0],[0,1,0,1]],name=['idx1','idx2'])

midx
Out[6]: 
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
           labels=[[1, 1, 0, 0], [0, 1, 0, 1]],
           names=['idx1', 'idx2'])

midx.set_labels([1,0,1,0],level=1)
Out[9]: 
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
           labels=[[1, 1, 0, 0], [1, 0, 1, 0]],
           names=['idx1', 'idx2'])

midx.swaplevel(0,1)
Out[11]: 
MultiIndex(levels=[['c', 'd'], ['a', 'b']],
           labels=[[0, 1, 0, 1], [1, 1, 0, 0]],
           names=['idx2', 'idx1'])

pd.MultiIndex.from_arrays([['a','a','b','b'],['c','d','c','d']],names=['idx1','idx2'])
Out[12]: 
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
           names=['idx1', 'idx2'])
复制代码

MultiIndex的第一个参数levels是每个级别的唯一标签列表,是一个两层嵌套的序列,外层对应级别,内层对应唯一标签; 第二个参数labels是所有记录在每个级别上选取的标签序号,也是一个两层嵌套的序列,外层对应级别,内层对应记录,新版本中已被codes参数取代; 第四个参数names是每个级别的名称。

MultiIndex提供了一些辅助方法,set_levelsset_labelsset_names可以设置整体或是某一级别的索引属性,通过level参数指定级别,默认设置整体; swaplevel可以交换级别,droplevel可以删除级别,sortlevel可以对指定级别排序; from_arrayfrom_tuplesfrom_productfrom_frame方法可从其他结构的数据中创建索引。

2. 数据序列Series

s=pd.Series([1,2,3,4],name='s1')

s
Out[100]: 
0    1
1    2
2    3
3    4
Name: s1, dtype: int64

pd.Series([[1,2],[3,4]],index=['row1','row2'])
Out[101]: 
row1    [1, 2]
row2    [3, 4]
dtype: object

s.dtype
Out[102]: dtype('int64')

s.name
Out[103]: 's1'

s.values
Out[104]: array([1, 2, 3, 4], dtype=int64)

s.index
Out[105]: RangeIndex(start=0, stop=4, step=1)

s.shape
Out[106]: (4,)
复制代码

核心数据模型其一,由序列名name、标签索引index、值数组(一维)values组成。用于存放一维数据,只有一个轴方向:0,shape属性可以查看数据集的形状。

创建时只能接收一维序列数据(list,tuple,ndarray),超过一维的将后面的维度看作元素的维度,会根据传入的数据自动判断类型,也可通过dtype参数显示指定。

默认情况下会生成范围索引,可通过index参数指定一个一维序列作为索引,也可在创建后直接为index属性赋值。

3. 数据框DataFrame

df=pd.DataFrame([[1,'a'],[2,'b']],columns=['col1','col2'])

df
Out[108]: 
   col1 col2
0     1    a
1     2    b

df.dtypes
Out[113]: 
col1     int64
col2    object
dtype: object

df.index
Out[114]: Int64Index([1, 2], dtype='int64', name='col1')

df.columns
Out[116]: Index(['col1', 'col2'], dtype='object')

df.values
Out[117]: 
array([[1, 'a'],
       [2, 'b']], dtype=object)

df.col2
Out[125]: 
col1
1    a
2    b
Name: col2, dtype: object

pd.DataFrame({
   
   'col1':[1,3],'col2':['a','b']})
Out[126]: 
   col1 col2
0     1    a
1     3    b

df.shape
Out[127]: (2, 2)
复制代码

核心数据模型其二,也就是数据表,由列标签索引columns、行标签索引index、值数组(二维)values组成。用于存放二维数据,有两个轴方向:0和1,对应行坐标和列坐标,shape属性可以查看数据集的形状。列数据的访问可以通过与列名相同的属性名访问,仅在定义了字符串列名时可用,一个单列即是一个Series

创建时只能接收二维序列数据(list,tuple,ndarray),超过二维的将后面的维度看作元素的维度,会根据传入的数据自动判断类型,也可通过dtype参数显示指定,与numpy不太一样的是,DataFrame的列可以定义不同的数据类型,通过创建时的自动判断,或是筛选出列后转换类型,DataFrame.dtypes属性可查看所有列的数据类型。相比numpy,pandas的DataFrame创建还增加了对dict数据源的支持,key对应列名,value对应列数据。

默认情况下会生成范围索引,可通过index参数指定一个一维序列作为索引,也可在创建后直接为index属性赋值,DataFrame.set_index方法可以返回替换了索引的数据框副本而不影响原数据。

DataFrame相当于Series的堆叠,沿DataFrame的行或列方向进行宽度为1的切片,得到的就是一个Series

原本pandas还提供了三维的数据模型Panel,但新版中已经废弃,可尝试使用多级索引MultiIndex来构造更高维度的数据集。

4. 分类数据Categorical

pandas提供了分类数据类型用于约束此类数据,该类型会限制分类标签的取值,并可为分类标签提供排序依据。

pd.Categorical(['a','b','b','c'],categories=['a','b'],ordered=True)
Out[14]: 
[a, b, b, NaN]
Categories (2, object): [a < b]

pd.Categorical(['a','b','b','c'])
Out[15]: 
[a, b, b, c]
Categories (3, object): [a, b, c]
复制代码

第一个参数values为所有分类标签的序列; 第二个参数categories为唯一分类标签的序列,当指定该参数后,values中不属于categories的标签会被替换为NaN,不指定时会根据values自动生成; 第三个参数ordered声明唯一分类标签是否指示排序方式,为True时会按categories中的顺序对标签标定大小关系,默认False

二. 数据类型与转换

返回目录

1. 数据类型

pandas支持的数据类型就是numpy的数据类型,在创建数据模型时同样可通过dtype参数指定。

常用的数据类型有:np.bool_(bool),np.int64(int),np.float64(float),np.datetime64(datetime),object(str等),pd.Categorical(category)。

更详细的类型说明可查看numpy的使用指南。 和numpy不太一样的是,numpy中int类型默认为np.int32,而pandas中默认np.int64;numpy中存储字符串优先采用定长的np.str_,而pandas中统一使用object

pandas数据模型使用单个ndarray作为基础数据,所以当pandas的每列采用不同数据类型时,作为数据来源的ndarray整体被设置为object数据类型。

2. 类型转换

df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])

df.dtypes
Out[49]: 
col1     int64
col2    object
dtype: object

df.col1.astype('float')
Out[50]: 
0    1.0
1    3.0
Name: col1, dtype: float64

pd.to_numeric(df.col2,errors='ignore')
Out[52]: 
0    2
1    a
Name: col2, dtype: object

pd.to_numeric(df.col2,errors='coerce')
Out[53]: 
0    2.0
1    NaN
Name: col2, dtype: float64
复制代码

pandas和numpy一样主要使用astype进行类型转换,该方法返回转换后数据,需要在原数据上更改时可以用返回值去覆盖原数据。

当需要进行一些可能会失败的转换时,可以考虑使用专用的方法,例如pd.to_numeric用于将一个Series转换为数字类型,errors参数可以指定对错误的处理方式:'coerce'表示强制转换,不能转换的元素会替换为NaN'ignore'表示存在无法转换的元素时会放弃转换。 当需要对DataFrame整体应用转换时,可使用apply方法。

三. 数组与统计运算

返回目录

1. 运算符和标量值函数

pandas重载了python的大部分运算符,可以直接进行数组计算,numpy的标量值函数也可直接使用,这些运算都是将原本作用于单个元素的运算拓展到整个数组。

df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])

df+df
Out[57]: 
   col1 col2
0     2   22
1     6   aa

np.sqrt(df.col1)
Out[201]: 
0    1.000000
1    1.732051
Name: col1, dtype: float64
复制代码

使用的运算符和函数必须对参与运算的所有数据类型都是有意义的,否则会报错。

匹配方式

s1=pd.Series([1,2,3,4],index=[0,1,2,3])
s2=pd.Series([5,6,7,8],index=[1,2,3,4])

s1+s2
Out[156]: 
0     NaN
1     7.0
2     9.0
3    11.0
4     NaN
dtype: float64
复制代码

此处需要注意pandas和numpy的区别,pandas的数组运算在元素匹配上是基于标签索引的,未能匹配到的位置会被替换为NaN,numpy则是基于位置索引。

2. 统计方法

聚合函数

pandas继承了numpy的聚合函数:summeanmaxmin等。 可通过SeriesDataFrame的方法调用,或是调用numpy下的静态方法。

df.sum()
Out[58]: 
col1     4
col2    2a
dtype: object

np.max(df)
Out[60]: 
col1    3
col2    a
dtype: object

df.agg({
   
   'col1':'max','col2':'sum'})
Out[114]: 
col1     3
col2    2a
dtype: object

df.agg(['max','sum'])
Out[115]: 
     col1 col2
max     3    a
sum     4   2a
复制代码

通过pandas数据模型的方法调用时, 第一个参数axis可以指定统计的轴,Series指定该参数没有意义,DataFrame默认沿轴0统计,即按列统计。pandas无法指定对所有轴展开统计,如有需要可以使用numpy的方法; 第二个参数skipna可以指示是否跳过NaN值; 第三个参数level用于在存在多级索引的情况下指定某一级索引进行统计; 第四个参数numeric_only用于指定是否只对数字应用计算。

当对DataFrame沿行方向统计时,由于不同列的数据类型可能不一样,需保证对应运算是有意义的,否则无法得到期望的结果。

agg方法是aggregate方法的简写,用于对不同列应用不同聚合函数或是多种聚合函数,可以传入list或是dict声明统计方式。

分组统计

pandas提供了类似于sql的groupby方法用于分组统计。

df=pd.DataFrame([['a','c',1],['a','d',2],['b','d',3]],columns=['col1','col2','col3'])

In [89]: df
Out[89]: 
  col1 col2  col3
0    a    c     1
1    a    d     2
2    b    d     3

result=df.groupby(by=['col1','col2']).agg(['max','min'])

result
Out[94]: 
          col3    
           max min
col1 col2         
a    c       1   1
     d       2   2
b    d       3   3

result.sum(level=0)
Out[95]: 
     col3    
      max min
col1         
a       3   3
b       3   3

gb=df.groupby(by=['col1','col2'])

gb.groups
Out[141]: 
{('a', 'c'): Int64Index([0], dtype='int64'),
 ('a', 'd'): Int64Index([1], dtype='int64'),
 ('b', 'd'): Int64Index([2], dtype='int64')}

gb.get_group(('a','c'))
Out[142]: 
  col1 col2  col3
0    a    c     1
复制代码

只调用groupby方法会得到一个DataFrameGroupBy对象,通过其groups方法可查看所有分组信息,get_group方法可获取指定分组。 该对象可调用各种聚合函数,或调用agg方法进行复合的聚合统计,返回包含多级索引的DataFrame统计结果表,对于结果表,可以继续应用统计函数并通过level参数指定索引级别进行二次统计。

3. 应用自定义函数

除pandas和numpy提供的函数外,还可以自定义函数并使用applyapplymapmap方法快速应用于整个数据集。

df.apply(lambda x: x.col1+x.col2, axis=1)
Out[119]: 
0    3
1    7
dtype: int64

def add(row):
    return row.col1+row.col2

df.apply(add, axis=1)
Out[121]: 
0    3
1    7
dtype: int64

df.applymap(lambda x: x*2)
Out[122]: 
   col1  col2
0     2     4
1     6     8

def double(item):
    return item*2

df.applymap(double)
Out[124]: 
   col1  col2
0     2     4
1     6     8

s=pd.Series(['a','b','b'])

s.map(lambda x: x*2)
Out[129]: 
0    aa
1    bb
2    bb
dtype: object

s.map({
   
   'a':'c','b':'d'})
Out[130]: 
0    c
1    d
2    d
dtype: object
复制代码

DataFrameapplyapplymap两个方法: apply将函数应用于每行或者每列,axis参数指定应用函数的轴方向,值为0表示按列应用,即逐列作为函数的参数进行计算,值为1表示按行应用,默认为0; applymap将函数应用于每个元素。

Series只有一个map方法,用于将函数应用于元素,除此以外,还提供值映射的功能,输入dict类型时会根据key-value映射将相应的值替换。

支持lambda匿名函数。

4. 广播

l2=[1,2]
a2=np.array(l2)
s2=pd.Series(l2)
df21=pd.DataFrame([1,2])
df12=pd.DataFrame([[1,2]])
l22=[[1,2],[3,4]]
a22=np.array(l22)
df22=pd.DataFrame(l22)
df23=pd.DataFrame([[3,4,5],[6,7,8]])

df22+l2
Out[99]: 
   0  1
0  2  4
1  4  6

df22+a2
Out[100]: 
   0  1
0  2  4
1  4  6

df22+s2
Out[101]: 
   0  1
0  2  4
1  4  6

df22+df21
Out[102]: 
   0   1
0  2 NaN
1  5 NaN

df22+df12
Out[103]: 
     0    1
0  2.0  4.0
1  NaN  NaN

df23+s2
Out[104]: 
     0    1   2
0  4.0  6.0 NaN
1  7.0  9.0 NaN

df21+df12
Out[130]: 
     0   1
0  2.0 NaN
1  NaN NaN
复制代码

pandas的广播机制继承自numpy但有不一样的地方: 标量值会与DataFrameSeries中每个元素进行同样的计算; Series或一维list或一维ndarray会与DataFrame的每一行进行运算,Series在长度不足以匹配DataFrame的行时不足部分会替换为NaN,其他两种长度不足会报错; DataFrameDataFrame进行运算会按元素匹配,无论行列,长度不足的部分都会替换为NaN; 二维ndarrayDataFrame的运算遵循numpy的广播规则,长度不足且为1的轴会被广播至同等大小; 二维listDataFrame的运算不被支持。

四. 查询和关联

返回目录

1. 索引查找

(1). 索引器格式

单值选取:[value,...] 多值选取:[[value1,value2],...] 范围选取:[start:end:step,...]

start表示区间的开始,默认值0,end表示区间的结束(不包含),默认值等于轴长度,step表示选取的步长,默认值1,采用默认值的参数可以省略,[:,...]表示对应轴方向上全部选取。

pandas中索引器的格式与numpy差不多,但用法有区别。pandas除了numpy的位置索引,还增加了标签索引,虽然可以对SeriesDataFrame直接使用索引器,但用法被严格限制,建议改用ilocloc方法进行索引。

(2). 直接索引

df=pd.DataFrame(np.arange(1,10).reshape((3,3)),columns=['col1','col2','col3'],index=['row1','row2','row3'])

df[0:3:2]
Out[158]: 
      col1  col2  col3
row1     1     2     3
row3     7     8     9

df['row1':'row3':2]
Out[161]: 
      col1  col2  col3
row1     1     2     3
row3     7     8     9

df['col2']
Out[162]: 
row1    2
row2    5
row3    8
Name: col2, dtype: int32

df[['col1','col3']]
Out[163]: 
      col1  col3
row1     1     3
row2     4     6
row3     7     9

df['col2'][1:3]
Out[168]: 
row2    5
row3    8
Name: col2, dtype: int32
复制代码

直接索引提供了有限的几种使用方式:按行位置进行索引切片、按行标签进行索引切片、按列标签取列、按列标签列表取多列、布尔索引筛选行、索尔索引筛选元素等。 一次索引器只能使用一种方式,不能行列同时操作,如有需要,可进行连续索引。

(3). loc和iloc索引

df.loc['row1','col1']
Out[169]: 1

df.loc['row1':'row3':2,'col1':'col3':2]
Out[170]: 
      col1  col3
row1     1     3
row3     7     9

df.iloc[0,0]
Out[185]: 1

df.iloc[0:3:2,0:3:2]
Out[186]: 
      col1  col3
row1     1     3
row3     7     9
复制代码

loc专用于标签索引,iloc专用于位置索引,索引器可接收单值、列表、范围、布尔索引,可同时索引行和列。

(4). 布尔索引

df>5
Out[190]: 
       col1   col2   col3
row1  False  False  False
row2  False  False   True
row3   True   True   True

df[df>5]
Out[191]: 
      col1  col2  col3
row1   NaN   NaN   NaN
row2   NaN   NaN   6.0
row3   7.0   8.0   9.0

df['col1']>2
Out[192]: 
row1    False
row2     True
row3     True
Name: col1, dtype: bool

df.loc[df['col1']>2]
Out[193]: 
      col1  col2  col3
row2     4     5     6
row3     7     8     9

df.loc[df['col1']>2,df.iloc[1]>5]
Out[196]: 
      col3
row2     6
row3     9

df.iloc[df['col1'].values>2]
Out[208]: 
      col1  col2  col3
row2     4     5     6
row3     7     8     9
复制代码

布尔索引是一种比较特殊的索引,通过对pandas或numpy的数据模型进行逻辑运算得到,与源数据结构相同,数据类型为bool,用于标识每个元素是否符合逻辑运算的条件。在索引器中使用布尔索引可以筛选出符合条件的数据。

在直接索引时,二维布尔索引可以用于筛选DataFrame的元素,形状不变,不符合条件的元素会被替换为NaN,这一点和numpy不一样,numpy进行同样形式的筛选时会将符合条件的元素构造为新的一维数组返回;一维布尔索引只可以用于筛选行数据;

在使用loc索引时,不能使用二维布尔索引,只能针对每个轴使用一维布尔索引,并且必须是由Series运算得到的带有标签索引的布尔索引; 在使用iloc索引时,同样不能使用二维布尔索引,只能针对每个轴使用一维布尔索引,并且必须是由一维ndarray运算得到的不含标签索引的布尔索引(Series.values可得到对应的ndarray)。

(5). 指定值查找

df=pd.DataFrame({
   
   'a':[np.nan,1,2],'b':[3,np.nan,4]})

df
Out[142]: 
     a    b
0  NaN  3.0
1  1.0  NaN
2  2.0  4.0

df.isin([2,3])
Out[143]: 
       a      b
0  False   True
1  False  False
2   True  False

df.isna()
Out[144]: 
       a      b
0   True  False
1  False   True
2  False  False
复制代码

isin方法用于查找存在于指定列表中的值,isna方法用于查找NaN值,两方法都会返回布尔索引,通常结合索引器使用。

2. 表连接

pandas提供了类似于sql的joinmergeconcat方法进行表连接。

(1). 索引连接

df1=pd.DataFrame([[1,2],[3,4]],columns=['col1','col2'],index=[1,0])
df2=pd.DataFrame([[5,6],[7,8]],columns=['col3','col4'],index=[0,1])

df1.join(df2,how='inner')
Out[229]: 
   col1  col2  col3  col4
1     1     2     7     8
0     3     4     5     6
复制代码

join方法根据索引进行表连接,how参数指定连接方式,有inner内连接、outer外连接、left左连接、right右连接 这几种,默认为left

此处的join和sql中的join并不一样。

(2). 键连接

df1=pd.DataFrame({
   
   'col1':[1,2,3],'col2':[4,5,6]})
df2=pd.DataFrame({
   
   'col2':[4,5,7],'col3':[1,2,2]})

df1.merge(df2)
Out[235]: 
   col1  col2  col3
0     1     4     1
1     2     5     2

df1.merge(df2,how='left',left_on='col1',right_on='col3')
Out[237]: 
   col1  col2_x  col2_y  col3
0     1       4     4.0   1.0
1     2       5     5.0   2.0
2     2       5     7.0   2.0
3     3       6     NaN   NaN
复制代码

merge方法根据指定键(列)进行表连接,通过on参数(相同键)或left_onright_on参数(不同键)指定,默认会将两表中都存在的键作为连接键;how参数指定连接方式,有inner内连接、outer外连接、left左连接、right右连接 这几种,默认为inner

该方法才是sql中join的等效方法。

(3). 拼接

df1=pd.DataFrame({
   
   'col1':[1,2,3],'col2':[4,5,6]})
df2=pd.DataFrame({
   
   'col2':[4,5,7],'col3':[1,2,2]})

pd.concat([df1,df2])
Out[241]: 
   col1  col2  col3
0   1.0     4   NaN
1   2.0     5   NaN
2   3.0     6   NaN
0   NaN     4   1.0
1   NaN     5   2.0
2   NaN     7   2.0

pd.concat([df1,df2],join='inner')
Out[242]: 
   col2
0     4
1     5
2     6
0     4
1     5
2     7

pd.concat([df1,df2],axis=1)
Out[243]: 
   col1  col2  col2  col3
0     1     4     4     1
1     2     5     5     2
2     3     6     7     2
复制代码

用于拼接表,等效于sql中的union all。

axis参数指定用于拼接的轴,默认0;join参数指定其他轴的处理方式,inner表示只返回都存在的项,outer表示全部返回,默认outer

拼接后的结果表中可能会有行索引或列索引上的重复,可以视需要重整索引。

五. 增删改

返回目录

1. 更新

df=pd.DataFrame({
   
   'a':[1,2],'b':[3,4]})

df.iloc[0,0]=0

df[df>2]+=1

df
Out[262]: 
   a  b
0  0  4
1  2  5

df['a']=[2,1]

df
Out[266]: 
   a  b
0  2  4
1  1  5

df[:]=[1,2]

df
Out[269]: 
   a  b
0  1  2
1  1  2
复制代码

更新数据的方式与numpy一样,索引筛选数据后直接赋值就行了,可以对所有元素赋值同一个标量,也可赋值同样形状的数据集,或是对DataFrame每行赋值同样的数据序列。

2. 增加

df=pd.DataFrame({
   
   'a':[1,2],'b':[3,4]})

df['c']=[5,6]

df
Out[248]: 
   a  b  c
0  1  3  5
1  2  4  6

df.loc[2]=-1

df
Out[253]: 
   a  b  c
0  1  3  5
1  2  4  6
2 -1 -1 -1

df.insert(0,'new',[0,0,0])

df
Out[255]: 
   new  a  b  c
0    0  1  3  5
1    0  2  4  6
2    0 -1 -1 -1
复制代码

借助索引器可直接为新行或是新列赋值。

insert方法可以在指定位置插入新列,loc参数指定位置索引,column参数指定列名,value指定新列的数据。

3. 删除

df=pd.DataFrame({
   
   'a':[1,2,3],'b':[4,5,6]})

df[df['a']>2]
Out[277]: 
   a  b
2  3  6

df.drop([0,2])
Out[281]: 
   a  b
1  2  5

df.drop('a',axis=1)
Out[282]: 
   b
0  4
1  5
2  6
复制代码

删除数据最灵活的方法就是通过索引筛去不需要的数据。

也可通过drop删除指定索引标签的数据,labels指定要删除的标签,可以是标量或是列表,axis参数指定查找索引标签的轴,默认为0。该方法是根据索引标签而不是位置去删除的,所以如果指定标签存在重复,这些数据会一起被删除。

若想留存被删除的列(比如想将该列插入另一个位置),可使用pop方法弹出列。

4. 重构索引

df=pd.DataFrame({
   
   'a':[1,2],'b':[3,4]})

df.reindex(columns=['a','b','c','d'],fill_value=0)
Out[256]: 
   a  b  c  d
0  1  3  0  0
1  2  4  0  0
复制代码

reindex方法用于重构索引,可以实现复杂的结构变更,包括行列的增加、删除、移位,index设置新的行索引,columns参数设置新的列索引,已存在的索引会和数据一起被移至新的位置,不存在的将被创建,fill_value参数可以指定新增行列的填充值。

5. 行列转置

df=pd.DataFrame({
   
   'a':[1,2],'b':[3,4]})

df
Out[134]: 
   a  b
0  1  3
1  2  4

df.T
Out[135]: 
   0  1
a  1  2
b  3  4
复制代码

DataFrame.T用于实现行列转置,整个数据集将沿左上至右下的对角线翻转。 Series调用转置方法是无效的,如果需要转置,先调用to_frame方法转为DataFrame

6. 缺失值填充

df=pd.DataFrame({
   
   'a':[np.nan,1,3],'b':[2,np.nan,6]})

df
Out[96]: 
     a    b
0  NaN  2.0
1  1.0  NaN
2  3.0  6.0

df.fillna(0)
Out[97]: 
     a    b
0  0.0  2.0
1  1.0  0.0
2  3.0  6.0

df.fillna(df.mean())
Out[98]: 
     a    b
0  2.0  2.0
1  1.0  4.0
2  3.0  6.0

df.dropna()
Out[120]: 
     a    b
2  3.0  6.0

df[df.isna()]=0

df
Out[122]: 
     a    b
0  0.0  2.0
1  1.0  0.0
2  3.0  6.0
复制代码

fillna方法用于填充缺失值,第一个参数value设置用于填充的值,可传入标量,对所有列填充同样的值,也可传入字典或系列,对不同列填充不同的值;另一种用法是给第二个参数method赋值,'ffill''bfill'分别表示用前一个和后一个有效值填充。

dropna方法用于直接删除带却缺失值的行或列:axis参数指定删除行(0)或列(1);how参数指定删除的条件,'all'表示全部值为NaN时删除,'any'表示有一个为NaN时删除;thresh参数设置在出现几个NaN时执行删除。

isna方法配合索引器也能对缺失值进行更新,可通过赋值标量对所有列填充同样的值,或是赋值序列对不同列填充不同的值。

六. 排序与去重

返回目录

1. 直接与间接排序

df=pd.DataFrame([[2,'a'],[1,'c'],[3,'b']],columns=['col1','col2'],index=[3,2,1])

df
Out[6]: 
   col1 col2
3     2    a
2     1    c
1     3    b

df.sort_index()
Out[7]: 
   col1 col2
1     3    b
2     1    c
3     2    a

df.sort_values('col1')
Out[8]: 
   col1 col2
2     1    c
3     2    a
1     3    b

df.loc[df['col2'].sort_values().index]
Out[21]: 
   col1 col2
3     2    a
1     3    b
2     1    c
复制代码

sort_index方法可以按索引排序,axis参数指定排序的轴,默认0,level参数指定用于排序的多级索引的级别,默认None,ascending参数指定是否升序,默认True。

sort_values方法可以按指定键排序,by参数指定用于排序的键,axis参数指定排序的轴,默认0,ascending参数指定是否升序,默认True。

间接排序可通过loc方法传入排序后的标签索引实现,排序前两个数据模型的索引必须一致;iloc方法类似,需要传入经过numpy的argsort方法排序后的位置索引。

2. 去重

df=pd.DataFrame({
   
   'a':[1,2,2,2],'b':[3,3,4,4]})

df
Out[10]: 
   a  b
0  1  3
1  2  3
2  2  4
3  2  4

df.duplicated()
Out[11]: 
0    False
1    False
2    False
3     True
dtype: bool

df.drop_duplicates()
Out[12]: 
   a  b
0  1  3
1  2  3
2  2  4

df.drop_duplicates('a',keep='last')
Out[14]: 
   a  b
0  1  3
3  2  4
复制代码

duplicated方法用于返回标识去重结果的一维布尔数组,保留的项为True。subset参数指定参与去重的行或列标签,默认使用所有列;keep参数指定保留方式,'first'表示保留第一项,'last'表示保留最后一项,None表示不保留。

drop_duplicates方法用于返回去重结果。subsetkeep参数的作用和duplicated一样。

七. 乱序和抽样

返回目录

1. 随机排序

df=pd.DataFrame({
   
   'a':[1,2,3],'b':[4,5,6]})

df.iloc[np.random.permutation(df.shape[0])]
Out[25]: 
   a  b
1  2  5
0  1  4
2  3  6

df.sample(frac=1.)
Out[27]: 
   a  b
0  1  4
2  3  6
1  2  5
复制代码

随机排序,用于打乱数据集。一种方法是通过numpy生成乱序索引,然后应用在pandas的iloc索引方法上;另一种方法是使用pandas的抽样方法sample,设置抽样比例frac参数为1.,采用默认的不放回抽样的方式,也可以达到同样的效果。

2. 抽样

df.sample(n=2)
Out[34]: 
   a  b
1  2  5
2  3  6

df.sample(frac=0.8,replace=True)
Out[36]: 
   a  b
1  2  5
1  2  5
复制代码

sample方法用于抽样,第一个参数n设置抽样数量,第二个参数frac设置抽样比例,第三个参数replace设置是否放回,默认False,第四个参数weight可设置样本权重,第五个参数random_state设置随机数种子。

八. 读写

返回目录

1. 读写csv

df=pd.DataFrame({
   
   'a':[1,2],'b':[3,4]},index=['r1','r2'])

df.to_csv()
Out[14]: ',a,b\nr1,1,3\nr2,2,4\n'

df.to_csv(index=False)
Out[15]: 'a,b\n1,3\n2,4\n'

df.to_csv("d:\\test.csv",index=False)

df2=pd.read_csv("d:\\test.csv")

df2
Out[18]: 
   a  b
0  1  3
1  2  4
复制代码

to_csv方法用于写入csv文件: 参数path_or_buf设置文件路径或对象,默认为None,表示直接返回完整的内容字符串; 参数sep设置分隔符,长度为1的字符串,默认为','; 参数na_rep设置缺失值填充,默认''; 参数float_format设置浮点数的格式字符串,如'%.2f'表示保留两位小数; 参数columns设置要写的列,默认None,表示全部; 参数header设置是否写入列名,默认True,如果给出字符串列表,则作为列别名; 参数index设置是否写入行索引标签,默认True; 参数index_label设置行索引列的列名,默认None,会直接使用索引的名称,不写入列名需要设置为False; 参数encoding设置编码格式,python3默认utf-8; 参数chunksize设置每次批量写入的块大小,默认一次写入全部数据。

read_csv方法用于读取csv文件: 参数filepath_or_buffer设置文件路径或类文件对象,必须赋值; 参数sep设置分隔符,长度为1的字符串,默认为','; 参数header设置作为列名的行号,可传入列表,会读取为多级索引,默认是第一行作为列名,当通过names显示传递列名时,该设置无效,另外,该参数会跳过注释行和空行; 参数names设置列名列表,默认为None,如果文件不含列名,header也应设置为None,该参数不能有重复项,会报错; 参数index_col设置作为行标签的列号,可传入列表,会读取为多级索引,默认不设置; 参数usecols设置要读取的列列表,可以是列位置(int)或是列名(str)的列表,也可以传入对列名进行逻辑判断的函数,结果为True的列将被返回; 参数prefix设置默认列名前缀,在没有设置列名时会将该前缀组合列号作为列名; 参数dtype设置数据类型,dict类型,键为列名,值为numpy数据类型,默认None; 参数skiprows设置开头要跳过的行数,需要传入int,也可以设置要跳过的行号,传入list of int或对行号进行逻辑判断的函数; 参数skipfooter设置尾部要跳过的行数,需要传入int; 参数nrows设置要读取的行数,用于分批读取大文件; 参数na_filter设置是否检测缺失值,默认True,在确定没有缺失值的情况下可以关闭以提升读取性能; 参数skip_blank_lines设置是否跳过空行,默认True; 参数encoding设置编码格式,python3默认utf-8; 参数error_bad_lines设置列数异常的坏行是否报错,默认TrueFalse时会直接剔除坏行; 参数chunksize设置分块的大小,如果设置,会按该大小分块读取并以迭代器返回。

2. 读写excel

df=pd.DataFrame({
   
   'a':[1,2],'b':[3,4]},index=['r1','r2'])

df.to_excel('d:\\test.xlsx',sheet_name='test1',index=False)

df2=pd.read_excel('d:\\test.xlsx',sheet_name=0)

df2
Out[9]: 
   a  b
0  1  3
1  2  4
复制代码

to_excel方法用于写入xls或xlsx文件: 参数excel_writer设置文件路径或ExcelWriter,必须赋值; 参数sheet_name设置要读取的工作表名称,默认'Sheet1'; 参数na_rep设置缺失值填充,默认''; 参数float_format设置浮点数的格式字符串,如'%.2f'表示保留两位小数; 参数columns设置要写入的列,为列名的序列; 参数header设置是否写入列名,默认True,当输入字符串列表时会当作列的别名; 参数index设置是否写入行索引标签,默认True; 参数index_label设置行索引列的列名,当存在多级索引时应当输入字符串列表,默认None,会直接使用索引的名称; 参数startrow设置写入的起始行,默认0; 参数startcol设置写入的起始列,默认0; 参数merge_cells设置单元格是否合并,默认True

read_excel方法用于读取xls或xlsx文件: 参数io设置文件路径或Excel文件对象,必须赋值; 参数sheet_name设置要读取的工作表,可以传入序号(int)或工作表名(str)或是包含前两种的列表,传入None表示全部,默认0; 参数header设置解析为列名的行号,传入行号的列表时会解析为多级索引,如果没有列名,需要设置为None; 参数names设置列名,与header配合使用,默认None; 参数index_col设置解析为行标签的列号,传入列号的列表时会解析为多级索引,默认None; 参数usecols设置需要返回的列,可传入列号的列表list of int、列名的列表list of str、用逗号分隔的列名序列(例如 ‘A,B,C’)或用冒号标识的列名范围(例如 ‘A:E’)str,也可传入对列名进行逻辑判断的函数,结果为True的列将被返回; 参数dtype设置数据类型,dict类型,键为列名,值为numpy数据类型,默认None; 参数skiprows设置开头要跳过的行数,需要传入int,也可以设置要跳过的行号,传入list of int或对行号进行逻辑判断的函数; 参数skipfooter设置尾部要跳过的行数,需要传入int

当sheetname不明确,需要获取全部sheetname时,可用以下方法

excel=pd.ExcelFile(file_path)
excel.sheetname
复制代码

3. 读写sql

import sqlalchemy as sqla
username='sa'
password='123456'
server='127.0.0.1'
database='Test'
charset='utf8'
engine = sqla.create_engine('mssql+pymssql://{}:{}@{}/{}?charset={}'.format(username,password,server,database,charset))

df=pd.DataFrame({
   
   'a':[1,2],'b':[3,4]},index=['r1','r2'])

df.to_sql('test1',engine,if_exists='append',index=False)
df.to_sql('test1',engine,if_exists='append',index=False)

df2=pd.read_sql('select * from test1',engine)

df2
Out[28]: 
     a    b
0  1.0  3.0
1  2.0  4.0
2  1.0  3.0
3  2.0  4.0
复制代码

to_sql方法用于写入数据库: 参数name设置要写入的表名,str类型; 参数conn设置数据库连接,sqlalchemy.engine.Engine类型,需要配合sqlalchemy库使用,通过create_engine方法创建,连接字符串格式形如'{数据库类型}+{驱动名}://{用户名}:{密码}@{服务器地址}:{端口号}/{数据库名}?charset={字符集}'; 参数if_exists设置表存在时的处理方式,'fail'表示抛出异常,'replace'表示替换现有表,'append'表示作为新数据插入现有表,默认'fail'; 参数index设置行索引标签是否作为一列写入,默认True; 参数index_label设置行索引标签列的列名,当存在多级索引时应当输入字符串列表,默认None,会直接使用索引的名称; 参数chunksize设置每次批量写入的块大小,默认一次写入全部数据; 参数dtype设置写入的数据类型,dict类型,键为列名,值为sqlalchemy数据类型;

read_sql方法用于读取数据库: 参数sql设置要执行的sql查询或表名; 参数conn设置数据库连接,sqlalchemy.engine.Engine类型; 参数index_col设置作为行标签索引的列名,传入列名的列表时会生成多级索引; 参数coerce_float设置是否尝试将一些非字符串非数字对象(如decimal.Decimal)的值转换为浮点数,默认True; 参数params设置传递给执行sql的参数列表,具体格式由使用的驱动决定; 参数parse_dates设置要解析为时间的列名列表,默认None; 参数columns设置要读取的列,仅在sql参数传入表名时有效,默认None读取全部列; 参数chunksize设置分块的大小,如果设置,会按该大小分块读取并以迭代器返回。

九. 快速绘图

返回目录

准备好pandas数据对象就可以调用方法直接绘图,pandas提供的快速绘图只适用于单次绘图,不便于构建复杂的图表,如有需要,使用matplotlib的方法创建图像和子图。

1. 曲线图

df=pd.DataFrame({
   
   'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})

fig=plt.figure(figsize=(12,4))

ax1=fig.add_subplot(1,2,1)
df.plot.line(ax=ax1)

ax2=fig.add_subplot(1,2,2)
df.plot.line(x='c',y=['a','b'],ax=ax2)

#plt.show()
Out[53]: <matplotlib.axes._subplots.AxesSubplot at 0x2aefe00ddd8>
复制代码

参数x设置作为x轴数据的列名(只能一个),参数y设置作为y轴数据的列名/列名列表,参数ax设置子图对象,默认None单独绘制。

plt.figure用于创建图像,figsize用于设置图像大小,tuple类型,格式为(weight,height); Figure.add_subplot用于创建子图,第一个参数设置纵向分区个数,第二个参数设置横向分区个数,第三个参数设置是第几个子图,是按分区先横后纵排列的; plt.plot用于显示绘制好的图像,在当前场景下可以省略,ipython调用完pandas的绘图方法后会直接显示。

绘制曲线图也可以使用plot(kind='line'),参数kind也可以省略,因为默认值就是'line'

2. 条形图

df=pd.DataFrame({
   
   'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})

fig=plt.figure(figsize=(12,4))

ax1=fig.add_subplot(1,2,1)
df.plot.bar(ax=ax1)

ax2=fig.add_subplot(1,2,2)
df.plot.bar(stacked=True,ax=ax2)

Out[147]: <matplotlib.axes._subplots.AxesSubplot at 0x2aeff4f17b8>
复制代码

参数stacked设置条形图是否堆叠。 水平条形图需要改用DataFrame.plot.barh方法。

3. 直方图

df=pd.DataFrame({
   
   'a':[1,2,2,3],'b':[3,3,3,4],'c':[1,2,3,4]})

fig=plt.figure(figsize=(12,4))

ax1=fig.add_subplot(1,2,1)
df.plot.hist(alpha=0.5,ax=ax1)

ax2=fig.add_subplot(1,2,2)
df.plot.hist(stacked=True,bins=4,ax=ax2)

Out[210]: <matplotlib.axes._subplots.AxesSubplot at 0x2aefff32080>
复制代码

参数alpha设置透明度,参数stacked设置是否堆叠,参数bins设置分箱数。

配合diff可以绘制按列拆分为子图的直方图:

df.diff().hist(bins=4)
Out[165]: 
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE805A4748>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000002AE805E3D68>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE80615390>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x000002AE8063DA20>]],
      dtype=object)
复制代码

4. 箱线图

df = pd.DataFrame(np.random.rand(10, 4),columns=['A','B','C','D'])

df.plot.box()
Out[167]: <matplotlib.axes._subplots.AxesSubplot at 0x2aeff644080>
复制代码

5. 散点图

df=pd.DataFrame(np.random.rand(50,3),columns=['a','b','c'])

fig=plt.figure(figsize=(12,4))

ax1=fig.add_subplot(1,2,1)
df.plot.scatter(x='a',y='b',s=df['c']*200,ax=ax1)

ax2=fig.add_subplot(1,2,2)
df[df['c']>=0.5].plot.scatter(x='a',y='b',color='b',label='c1',ax=ax2)
df[df['c']<0.5].plot.scatter(x='a',y='b',color='g',label='c2',ax=ax2)

Out[186]: <matplotlib.axes._subplots.AxesSubplot at 0x2ae81a82e48>
复制代码

参数
x设置作为x轴数据的列名(只能一个),参数
y设置作为y轴数据的列名(只能一个),参数
s设置点的大小,参数
color设置点的颜色,参数
label设置标签,需要为每个类别绘制不同颜色的点时,筛选出每个类别的数据分别绘制到同一个子图上,并指定颜色和标签。

6. 饼图

df=pd.DataFrame(2*np.random.rand(3,2),index=['a','b','c'],columns=['p1','p2'])

df.plot.pie(y='p1',figsize=(4,4))
Out[204]: <matplotlib.axes._subplots.AxesSubplot at 0x2ae81f66cf8>
复制代码

df.plot.pie(subplots=True,figsize=(8.5,4))
Out[206]: 
array([<matplotlib.axes._subplots.AxesSubplot object at 0x000002AE8171BEB8>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x000002AEFFFD78D0>],
      dtype=object)
复制代码

有两种绘制方式,一是参数y指定一个列作为取值绘制饼图,二是设置参数subplotsTrue,会用每个列的数据绘制子图。 figsize是绘图的通用参数,用于设置图像大小。

十. 特殊类型处理

返回目录

1. 字符串处理

(1). 运算符

df=pd.DataFrame([['a','head',1],['b','Body',2],['c','FOOT',3]],
                columns=['col1','col2','col3'])

df['col1']+df['col2']
Out[54]: 
0    ahead
1    bBody
2    cFOOT
dtype: object

df['col1']*df['col3']
Out[55]: 
0      a
1     bb
2    ccc
dtype: object
复制代码

字符串类型支持两种运算符操作:拼接(str + str)和重复(str * int)

(2). 字符串方法

Series.str下封装了用于字符串处理的方法,python中str类的大部分方法都被继承了。 下面演示一些常用的方法:

索引器

df['col2'].str[:2]
Out[60]: 
0    he
1    Bo
2    FO
Name: col2, dtype: object
复制代码

字符串长度

df['col2'].str.len()
Out[73]: 
0    4
1    4
2    4
Name: col2, dtype: int64
复制代码

大小写转换

#转大写
#isupper方法判断是否大写
df['col2'].str.upper()
Out[56]: 
0    HEAD
1    BODY
2    FOOT
Name: col2, dtype: object

#转小写
#islower方法判断是否大写
df['col2'].str.lower()
Out[57]: 
0    head
1    body
2    foot
Name: col2, dtype: object

#首字母大写
df['col2'].str.capitalize()
Out[58]: 
0    Head
1    Body
2    Foot
Name: col2, dtype: object

#大小写互转
df['col2'].str.swapcase()
Out[59]: 
0    HEAD
1    bODY
2    foot
Name: col2, dtype: object
复制代码

填充

#填充至width长度
#side可设置'left'/'right'/'both'
df['col2'].str.pad(width=10, side='right', fillchar='-')
Out[63]: 
0    head------
1    Body------
2    FOOT------
Name: col2, dtype: object

#居中填充
#等效于pad(side='both')
df['col2'].str.center(width=11, fillchar='*')
Out[66]: 
0    ****head***
1    ****Body***
2    ****FOOT***
Name: col2, dtype: object
复制代码

拼接

#将一列字符串拼接成一个字符串
#sep设置分隔符
df['col2'].str.cat(sep=',')
Out[67]: 'head,Body,FOOT'

#将两列字符串拼接成一列字符串
#na_rep设置空值填充
df['col2'].str.cat(['d','e',np.nan],sep=',',na_rep='?')
Out[68]: 
0    head,d
1    Body,e
2    FOOT,?
Name: col2, dtype: object

#将两列字符串拼接成一列字符串
#join设置连接方式
ss=pd.Series(['d','e','f'],index=[0,3,5])
df['col2'].str.cat(ss,sep=',',na_rep='?',join='left')
Out[69]: 
0    head,d
1    Body,?
2    FOOT,?
Name: col2, dtype: object

#将每个元素上的字符串列表拼接
ss=pd.Series([['a','b'],['c','d']])
ss.str.join(',')
Out[72]: 
0    a,b
1    c,d
dtype: object
复制代码

拆分

#拆分字符串并以列表作为元素返回
#pat分隔符默认为' ',可设置正则表达式用于分割
ss=pd.Series(['a,b,c','d,e'])
ss.str.split(pat=',')
Out[74]: 
0    [a, b, c]
1       [d, e]
dtype: object

#n限制分割的次数,expand设置是否将拆分后的字符串展开至列
ss.str.split(pat=',',n=1,expand=True)
Out[76]: 
   0    1
0  a  b,c
1  d    e
复制代码

查找与替换

#是否包含
#pat可设置一般字符串或正则表达式
df['col2'].str.contains('a')
Out[89]: 
0     True
1    False
2    False
Name: col2, dtype: bool

#正则匹配
#pat只能设置正则表达式
#另有startswith,endswith方法可用于匹配开头和结尾
#另有extract,extractall方法可用于抽取匹配的组
df['col2'].str.match('[a-z]*')
Out[90]: 
0    True
1    True
2    True
Name: col2, dtype: bool

#查找匹配并返回索引
#另有findall方法可查找全部匹配并以列表元素返回
#另有index方法可通过start,end设置查找范围
df['col2'].str.find('d')
Out[91]: 
0    3
1    2
2   -1
Name: col2, dtype: int64

#统计指定模式出现次数
df['col2'].str.count('O')
Out[92]: 
0    0
1    0
2    2
Name: col2, dtype: int64

#替换
#第一个参数pat设置匹配模式,第二个参数repl设置用于替换的字符串
#参数n设置替换次数
#另有translate方法用于批量映射字符
df['col2'].str.replace('d','e')
Out[93]: 
0    heae
1    Boey
2    FOOT
Name: col2, dtype: object
复制代码

删除首尾字符

#另有lstrip,rstrip方法分别用于删除首和尾的字符
df['col2'].str.strip('d')
Out[96]: 
0     hea
1    Body
2    FOOT
Name: col2, dtype: object

#可设置正则表达式
df['col2'].str.strip('[FT]')
Out[98]: 
0    head
1    Body
2      OO
Name: col2, dtype: object
复制代码

2. 时间处理

(1). 时间类型

pd.Timestamp('2017-01-01 20:30:00',freq='D')
Out[80]: Timestamp('2017-01-01 20:30:00', freq='D')

pd.Period('2017-01-01 20:30')
Out[81]: Period('2017-01-01 20:30', 'T')

pd.Timedelta('2 days 1 hours')
Out[82]: Timedelta('2 days 01:00:00')

pd.Timedelta(1,unit='Y')
Out[83]: Timedelta('365 days 05:49:12')

from datetime import datetime
pd.Timestamp(datetime.now())
Out[84]: Timestamp('2019-05-18 16:14:26.691659')
复制代码

pandas有两种时间类型:TimestampPeriodTimestampdtypedatetime64PerioddtypeobjectTimestamp创建时可以不指定时间频率freq参数,但会导致无法参与运算;Period则会根据输入的值自动设置freq。可转换datetime库的时间类型。

Timedelta是时间变化量类型,第一个参数value指定变化量,输入类型为int时需要配合第二个参数unit(单位)使用,和时间类型中的freq是一个意思,默认'ns';也可输入字符串类型,对应所有的拓展命名参数(days, seconds, microseconds,milliseconds, minutes, hours, weeks),可通过参数指定,或是以字符串形式声明。

支持的freq取值有(按从大到小排列):‘Y’, ‘M’, ‘W’, ‘D’, ‘days’, ‘day’, ‘hours’, hour’, ‘hr’, ‘h’, ‘m’, ‘minute’, ‘min’, ‘minutes’, ‘T’, ‘S’, ‘seconds’, ‘sec’, ‘second’, ‘ms’, ‘milliseconds’, ‘millisecond’, ‘milli’, ‘millis’, ‘L’, ‘us’, ‘microseconds’, ‘microsecond’, ‘micro’, ‘micros’, ‘U’, ‘ns’, ‘nanoseconds’, ‘nano’, ‘nanos’, ‘nanosecond’, ‘N’。

(2). 时间范围

生成

#时间范围
tr=pd.date_range(start='2017-01-01',periods=5,freq='2H')

tr
Out[7]: 
DatetimeIndex(['2017-01-01 00:00:00', '2017-01-01 02:00:00',
               '2017-01-01 04:00:00', '2017-01-01 06:00:00',
               '2017-01-01 08:00:00'],
              dtype='datetime64[ns]', freq='2H')

#另一种时间范围
pr=pd.period_range(start='2017-01-01',periods=5,freq='D')

pr
Out[9]: 
PeriodIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04',
             '2017-01-05'],
            dtype='period[D]', freq='D')

#时间差范围
tdr=pd.timedelta_range(start='1 day', end='2 days', freq='6H')

tdr
Out[11]: 
TimedeltaIndex(['1 days 00:00:00', '1 days 06:00:00', '1 days 12:00:00',
                '1 days 18:00:00', '2 days 00:00:00'],
               dtype='timedelta64[ns]', freq='6H')

#时间间隔范围
ir=pd.interval_range(start=pd.Timestamp('2017-01-01'),periods=3, freq='MS')

ir
Out[31]: 
IntervalIndex([(2017-01-01, 2017-02-01], (2017-02-01, 2017-03-01], (2017-03-01, 2017-04-01]]
              closed='right',
              dtype='interval[datetime64[ns]]')
复制代码

pd.date_rangepd.period_range用于时间范围的生成,pd.timedelta_range用于时间变化量范围的生成,pd.interval_range用于时间间隔范围的生成。

以上方法有几个相同功能的参数:
start参数指定范围的开始;end参数指定范围的结束;
periods参数指定生成的周期数(即数量);freq参数指定生成的频率(即间隔);
name参数指定生成的索引名称;closed参数指定区间闭合方式,支持的取值有'left''right'None(即两边都闭合),默认None

startendperiodsfreq这四个参数至少指定其中三个。

这些方法生成的都是索引类型,可通过.to_series().to_frame()转换为SerisDataFrame

变更

tr=pd.date_range(start='2017-01-01',periods=5,freq='2H')

#移动范围
tr.shift(-1,freq='D')
Out[172]: 
DatetimeIndex(['2016-12-31 00:00:00', '2016-12-31 02:00:00',
               '2016-12-31 04:00:00', '2016-12-31 06:00:00',
               '2016-12-31 08:00:00'],
              dtype='datetime64[ns]', freq='2H')

ts=pd.Series(np.arange(len(tr)),index=tr)

#按指定频率重采样
ts.asfreq(freq='4H')
Out[175]: 
2017-01-01 00:00:00    0
2017-01-01 04:00:00    2
2017-01-01 08:00:00    4
Freq: 4H, dtype: int32
复制代码

shift方法用于时间范围的移动,第一个参数n指定移动量,第二个参数freq指定频率。

asfreq方法用于按指定频率重采样,只能用于使用时间索引的SeriesDataFrame,第一个参数freq指定频率,第二个参数method指定填充NaN的方式,当新采样频率不能被旧频率整除时,会出现值为NaN的无效采样,可选'ffill'(前一个有效值)和'bfill'(后一个有效值),默认None(不填充)。

(3). 获取时间部分

时间类型

t=pd.Timestamp('2017-01-02 20:30:40.50')

t.date()
Out[101]: datetime.date(2017, 1, 2)

t.year
Out[102]: 2017

t.month
Out[103]: 1

t.day
Out[104]: 2

t.time()
Out[105]: datetime.time(20, 30, 40, 500000)

t.hour
Out[106]: 20

t.minute
Out[107]: 30

t.second
Out[108]: 40

t.microsecond
Out[109]: 500000

t.quarter
Out[110]: 1

t.weekday()
Out[118]: 0

t.day_name()
Out[119]: 'Monday'

t.week
Out[120]: 1
复制代码

时间类型的Series可调用.dt下的同名属性,datetimeweekday方法都变为以属性形式访问,day_name方法可通过weekday_name属性访问。

时间变化量类型

td=pd.Timedelta(weeks=0,days=1,hours=2,minutes=3,seconds=4,
                milliseconds=5,microseconds=6)

td.days
Out[141]: 1

td.seconds
Out[142]: 7384

td.microseconds
Out[143]: 5006

td.total_seconds()
Out[145]: 93784.005006
复制代码

Timedeltatotal_seconds方法获取总秒数;dayssecondsmicroseconds获取各个部分,只分这三个,yearsmonthshoursminutes等是没有的。

时间变化量类型的Series可调用.dt下的同名属性或方法。

(4). 类型转换

其他类型转时间

from datetime import datetime

t=pd.Timestamp(datetime.now())

p=pd.Period(t,freq='D')
复制代码

创建单个时间类型时可以直接传入支持转换的类型完成转换。 Period必须指定freq

ss=pd.Series(['2017-01-01','2017-01-02'])

ss.astype('datetime64')
Out[183]: 
0   2017-01-01
1   2017-01-02
dtype: datetime64[ns]

pd.to_datetime(ss)
Out[184]: 
0   2017-01-01
1   2017-01-02
dtype: datetime64[ns]
复制代码

SeriesDataFrameastype方法指定类型datetime64可以转换类型为时间,静态pd.to_datetime可以完成等效转换。

SeriesDataFrameto_periodto_timestamp方法是作用于索引而不是数据的,调用的是索引的同名方法,其中DatetimeIndexPeriodIndex是可通过这两个方法相互转换的。

时间转字符串

tr=pd.date_range(start='2017-01-01',periods=5,freq='D')

tr.strftime('%Y-%m-%d,%a')
Out[231]: 
Index(['2017-01-01,Sun', '2017-01-02,Mon', '2017-01-03,Tue', '2017-01-04,Wed',
       '2017-01-05,Thu'],
      dtype='object')
复制代码

Series类型可通过.dt下的同名方法调用转换方法。

支持的转换格式定义如下:

%y 年(两位)
%Y 年(四位)
%m
%d
%H 时(24小时制)
%I 时(12小时制)
%M
%S

%j 年内第几天
%p 上午或下午,AM或PM
%U 年内第几周,周日为一周的开始
%w 周,周日为一周的开始
%W 年内第几周,周一为一周的开始

% %Y-%m-%d %H:%M:%S的简写形式
%F %Y-%m-%d的简写形式
%D %m/%d/%y的简写形式

%a 本地的周简称
%A 本地的周名称
%b 本地的月简称
%B 本地的月名称
%c 本地的日期表示和时间表示
%x 本地的日期表示
%X 本地的时间表示
%Z 当前时区的名称
%% %号本身

(5). 时间运算

#标量值时间
pd.Period('2017-01-01 20:30:00',freq='D')+1
Out[253]: Period('2017-01-02', 'D')

ss1=pd.Series(['2017-01-01','2017-02-02'])
ss1=ss1.astype('datetime64')
ss2=pd.Series(['2017-01-05','2017-02-04'])
ss2=ss2.astype('datetime64')

#时间-时间
ss2-ss1
Out[255]: 
0   4 days
1   2 days
dtype: timedelta64[ns]

#获取时间变化量的属性
(ss2-ss1).dt.days
Out[256]: 
0    4
1    2
dtype: int64

#时间变化量缩放
(ss2-ss1)*2
Out[257]: 
0   8 days
1   4 days
dtype: timedelta64[ns]

#时间+时间变化量
ss1+pd.Timedelta(days=1)
Out[258]: 
0   2017-01-02
1   2017-02-03
dtype: datetime64[ns]
复制代码

支持以下几种运算:
时间 – 时间 = 时间变化量
时间变化量 + 时间变化量 = 时间变化量
时间变化量 * 整数 = 时间变化量
时间 + 时间变化量 = 时间
(时间变化量:perioddatetime,时间变化量:timedelta,整数:int)

标量值的TimestampPeriod在设置了freq的情况下可以直接加减整数。

转载于:https://juejin.im/post/5cbb34175188253772754097

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/106868.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号