内容简介:numpy中只有位置索引,而pandas还增加了标签索引,依赖于一个专用的pandas提供了多级索引以便于分组数据,可用于构造高维数据集,
numpy中只有位置索引,而pandas还增加了标签索引,依赖于一个专用的 Index 类型。
常规索引
In [64]: pd.Index([1,2,3])
Out[64]: Int64Index([1, 2, 3], dtype='int64')
In [65]: pd.Index([1.,2.,3.])
Out[65]: Float64Index([1.0, 2.0, 3.0], dtype='float64')
In [66]: pd.Index(['a','b','c'])
Out[66]: Index(['a', 'b', 'c'], dtype='object')
In [67]: pd.Index(range(10))
Out[67]: RangeIndex(start=0, stop=10, step=1)
In [68]: pd.Index(range(10)).values
Out[68]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int64)
In [80]: import datetime as dt
...: dt1=dt.datetime.now()
...: dt2=dt1+dt.timedelta(days=1)
In [81]: 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 计算也会自动产生多级索引。
In [5]: midx=pd.MultiIndex(levels=[['a','b'],['c','d']],labels=[[1,1,0,0],[0,1,0,1]],name=['idx1','idx2'])
In [6]: midx
Out[6]:
MultiIndex(levels=[['a', 'b'], ['c', 'd']],
labels=[[1, 1, 0, 0], [0, 1, 0, 1]],
names=['idx1', 'idx2'])
In [9]: 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'])
In [11]: midx.swaplevel(0,1)
Out[11]:
MultiIndex(levels=[['c', 'd'], ['a', 'b']],
labels=[[0, 1, 0, 1], [1, 1, 0, 0]],
names=['idx2', 'idx1'])
In [12]: 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_levels 、 set_labels 、 set_names 可以设置整体或是某一级别的索引属性,通过 level 参数指定级别,默认设置整体; swaplevel 可以交换级别, droplevel 可以删除级别, sortlevel 可以对指定级别排序; from_array 、 from_tuples 、 from_product 、 from_frame 方法可从其他结构的数据中创建索引。
2. 数据序列 Series
In [99]: s=pd.Series([1,2,3,4],name='s1')
In [100]: s
Out[100]:
0 1
1 2
2 3
3 4
Name: s1, dtype: int64
In [101]: pd.Series([[1,2],[3,4]],index=['row1','row2'])
Out[101]:
row1 [1, 2]
row2 [3, 4]
dtype: object
In [102]: s.dtype
Out[102]: dtype('int64')
In [103]: s.name
Out[103]: 's1'
In [104]: s.values
Out[104]: array([1, 2, 3, 4], dtype=int64)
In [105]: s.index
Out[105]: RangeIndex(start=0, stop=4, step=1)
In [106]: s.shape
Out[106]: (4,)
复制代码
核心数据模型其一,由序列名 name 、标签索引 index 、值数组(一维) values 组成。用于存放一维数据,只有一个轴方向:0, shape 属性可以查看数据集的形状。
创建时只能接收一维序列数据(list,tuple,ndarray),超过一维的将后面的维度看作元素的维度,会根据传入的数据自动判断类型,也可通过 dtype 参数显示指定。
默认情况下会生成范围索引,可通过 index 参数指定一个一维序列作为索引,也可在创建后直接为 index 属性赋值。
3. 数据框 DataFrame
In [107]: df=pd.DataFrame([[1,'a'],[2,'b']],columns=['col1','col2'])
In [108]: df
Out[108]:
col1 col2
0 1 a
1 2 b
In [113]: df.dtypes
Out[113]:
col1 int64
col2 object
dtype: object
In [114]: df.index
Out[114]: Int64Index([1, 2], dtype='int64', name='col1')
In [116]: df.columns
Out[116]: Index(['col1', 'col2'], dtype='object')
In [117]: df.values
Out[117]:
array([[1, 'a'],
[2, 'b']], dtype=object)
In [125]: df.col2
Out[125]:
col1
1 a
2 b
Name: col2, dtype: object
In [126]: pd.DataFrame({'col1':[1,3],'col2':['a','b']})
Out[126]:
col1 col2
0 1 a
1 3 b
In [127]: 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提供了分类数据类型用于约束此类数据,该类型会限制分类标签的取值,并可为分类标签提供 排序 依据。
In[14]: pd.Categorical(['a','b','b','c'],categories=['a','b'],ordered=True) Out[14]: [a, b, b, NaN] Categories (2, object): [a < b] In[15]: 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. 类型转换
In [48]: df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2'])
In [49]: df.dtypes
Out[49]:
col1 int64
col2 object
dtype: object
In [50]: df.col1.astype('float')
Out[50]:
0 1.0
1 3.0
Name: col1, dtype: float64
In [52]: pd.to_numeric(df.col2,errors='ignore')
Out[52]:
0 2
1 a
Name: col2, dtype: object
In [53]: 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的标量值函数也可直接使用,这些运算都是将原本作用于单个元素的运算拓展到整个数组。
In [56]: df=pd.DataFrame([[1,'2'],[3,'a']],columns=['col1','col2']) In [57]: df+df Out[57]: col1 col2 0 2 22 1 6 aa In [201]: np.sqrt(df.col1) Out[201]: 0 1.000000 1 1.732051 Name: col1, dtype: float64 复制代码
使用的运算符和函数必须对参与运算的所有数据类型都是有意义的,否则会报错。
匹配方式
In [154]: s1=pd.Series([1,2,3,4],index=[0,1,2,3]) In [155]: s2=pd.Series([5,6,7,8],index=[1,2,3,4]) In [156]: 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的聚合函数: sum 、 mean 、 max 、 min 等。 可通过 Series 和 DataFrame 的方法调用,或是调用numpy下的静态方法。
In [58]: df.sum()
Out[58]:
col1 4
col2 2a
dtype: object
In [60]: np.max(df)
Out[60]:
col1 3
col2 a
dtype: object
In [114]: df.agg({'col1':'max','col2':'sum'})
Out[114]:
col1 3
col2 2a
dtype: object
In [115]: 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 方法用于分组统计。
In [88]: 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
In [93]: result=df.groupby(by=['col1','col2']).agg(['max','min'])
In [94]: result
Out[94]:
col3
max min
col1 col2
a c 1 1
d 2 2
b d 3 3
In [95]: result.sum(level=0)
Out[95]:
col3
max min
col1
a 3 3
b 3 3
In [140]: gb=df.groupby(by=['col1','col2'])
In [141]: gb.groups
Out[141]:
{('a', 'c'): Int64Index([0], dtype='int64'),
('a', 'd'): Int64Index([1], dtype='int64'),
('b', 'd'): Int64Index([2], dtype='int64')}
In [142]: 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提供的函数外,还可以自定义函数并使用 apply 、 applymap 、 map 方法快速应用于整个数据集。
In [119]: df.apply(lambda x: x.col1+x.col2, axis=1)
Out[119]:
0 3
1 7
dtype: int64
In [120]: def add(row):
...: return row.col1+row.col2
In [121]: df.apply(add, axis=1)
Out[121]:
0 3
1 7
dtype: int64
In [122]: df.applymap(lambda x: x*2)
Out[122]:
col1 col2
0 2 4
1 6 8
In [123]: def double(item):
...: return item*2
In [124]: df.applymap(double)
Out[124]:
col1 col2
0 2 4
1 6 8
In [128]: s=pd.Series(['a','b','b'])
In [129]: s.map(lambda x: x*2)
Out[129]:
0 aa
1 bb
2 bb
dtype: object
In [130]: s.map({'a':'c','b':'d'})
Out[130]:
0 c
1 d
2 d
dtype: object
复制代码
DataFrame 有 apply 和 applymap 两个方法: apply 将函数应用于每行或者每列, axis 参数指定应用函数的轴方向,值为0表示按列应用,即逐列作为函数的参数进行计算,值为1表示按行应用,默认为0; applymap 将函数应用于每个元素。
Series 只有一个 map 方法,用于将函数应用于元素,除此以外,还提供值映射的功能,输入 dict 类型时会根据key-value映射将相应的值替换。
支持lambda匿名函数。
4. 广播
In [80]: 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]])
In [99]: df22+l2
Out[99]:
0 1
0 2 4
1 4 6
In [100]: df22+a2
Out[100]:
0 1
0 2 4
1 4 6
In [101]: df22+s2
Out[101]:
0 1
0 2 4
1 4 6
In [102]: df22+df21
Out[102]:
0 1
0 2 NaN
1 5 NaN
In [103]: df22+df12
Out[103]:
0 1
0 2.0 4.0
1 NaN NaN
In [104]: df23+s2
Out[104]:
0 1 2
0 4.0 6.0 NaN
1 7.0 9.0 NaN
In [130]: df21+df12
Out[130]:
0 1
0 2.0 NaN
1 NaN NaN
复制代码
pandas的广播机制继承自numpy但有不一样的地方: 标量值会与 DataFrame 或 Series 中每个元素进行同样的计算; Series 或一维 list 或一维 ndarray 会与 DataFrame 的每一行进行运算, Series 在长度不足以匹配 DataFrame 的行时不足部分会替换为 NaN ,其他两种长度不足会报错; DataFrame 与 DataFrame 进行运算会按元素匹配,无论行列,长度不足的部分都会替换为 NaN ; 二维 ndarray 与 DataFrame 的运算遵循numpy的广播规则,长度不足且为1的轴会被广播至同等大小; 二维 list 与 DataFrame 的运算不被支持。
四. 查询和关联
1. 索引查找
(1). 索引器格式
单值选取: [value,...] 多值选取: [[value1,value2],...] 范围选取: [start:end:step,...]
start 表示区间的开始,默认值0, end 表示区间的结束(不包含),默认值等于轴长度, step 表示选取的步长,默认值1,采用默认值的参数可以省略, [:,...] 表示对应轴方向上全部选取。
pandas中索引器的格式与numpy差不多,但用法有区别。pandas除了numpy的位置索引,还增加了标签索引,虽然可以对 Series 和 DataFrame 直接使用索引器,但用法被严格限制,建议改用 iloc 和 loc 方法进行索引。
(2). 直接索引
In [157]: df=pd.DataFrame(np.arange(1,10).reshape((3,3)),columns=['col1','col2','col3'],index=['row1','row2','row3'])
In [158]: df[0:3:2]
Out[158]:
col1 col2 col3
row1 1 2 3
row3 7 8 9
In [161]: df['row1':'row3':2]
Out[161]:
col1 col2 col3
row1 1 2 3
row3 7 8 9
In [162]: df['col2']
Out[162]:
row1 2
row2 5
row3 8
Name: col2, dtype: int32
In [163]: df[['col1','col3']]
Out[163]:
col1 col3
row1 1 3
row2 4 6
row3 7 9
In [168]: df['col2'][1:3]
Out[168]:
row2 5
row3 8
Name: col2, dtype: int32
复制代码
直接索引提供了有限的几种使用方式:按行位置进行索引切片、按行标签进行索引切片、按列标签取列、按列标签列表取多列、布尔索引筛选行、索尔索引筛选元素等。 一次索引器只能使用一种方式,不能行列同时操作,如有需要,可进行连续索引。
(3). loc和iloc索引
In [169]: df.loc['row1','col1']
Out[169]: 1
In [170]: df.loc['row1':'row3':2,'col1':'col3':2]
Out[170]:
col1 col3
row1 1 3
row3 7 9
In [185]: df.iloc[0,0]
Out[185]: 1
In [186]: df.iloc[0:3:2,0:3:2]
Out[186]:
col1 col3
row1 1 3
row3 7 9
复制代码
loc 专用于标签索引, iloc 专用于位置索引,索引器可接收单值、列表、范围、布尔索引,可同时索引行和列。
(4). 布尔索引
In [190]: df>5
Out[190]:
col1 col2 col3
row1 False False False
row2 False False True
row3 True True True
In [191]: df[df>5]
Out[191]:
col1 col2 col3
row1 NaN NaN NaN
row2 NaN NaN 6.0
row3 7.0 8.0 9.0
In [192]: df['col1']>2
Out[192]:
row1 False
row2 True
row3 True
Name: col1, dtype: bool
In [193]: df.loc[df['col1']>2]
Out[193]:
col1 col2 col3
row2 4 5 6
row3 7 8 9
In [196]: df.loc[df['col1']>2,df.iloc[1]>5]
Out[196]:
col3
row2 6
row3 9
In [208]: 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). 指定值查找
In [141]: df=pd.DataFrame({'a':[np.nan,1,2],'b':[3,np.nan,4]})
In [142]: df
Out[142]:
a b
0 NaN 3.0
1 1.0 NaN
2 2.0 4.0
In [143]: df.isin([2,3])
Out[143]:
a b
0 False True
1 False False
2 True False
In [144]: df.isna()
Out[144]:
a b
0 True False
1 False True
2 False False
复制代码
isin 方法用于查找存在于指定列表中的值, isna 方法用于查找NaN值,两方法都会返回布尔索引,通常结合索引器使用。
2. 表连接
pandas提供了类似于sql的 join 、 merge 、 concat 方法进行表连接。
(1). 索引连接
In [227]: df1=pd.DataFrame([[1,2],[3,4]],columns=['col1','col2'],index=[1,0]) In [228]: df2=pd.DataFrame([[5,6],[7,8]],columns=['col3','col4'],index=[0,1]) In [229]: 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). 键连接
In [233]: df1=pd.DataFrame({'col1':[1,2,3],'col2':[4,5,6]})
In [234]: df2=pd.DataFrame({'col2':[4,5,7],'col3':[1,2,2]})
In [235]: df1.merge(df2)
Out[235]:
col1 col2 col3
0 1 4 1
1 2 5 2
In [237]: 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_on 和 right_on 参数(不同键)指定,默认会将两表中都存在的键作为连接键; how 参数指定连接方式,有 inner 内连接、 outer 外连接、 left 左连接、 right 右连接 这几种,默认为 inner 。
该方法才是sql中join的等效方法。
(3). 拼接
In [239]: df1=pd.DataFrame({'col1':[1,2,3],'col2':[4,5,6]})
In [240]: df2=pd.DataFrame({'col2':[4,5,7],'col3':[1,2,2]})
In [241]: 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
In [242]: pd.concat([df1,df2],join='inner')
Out[242]:
col2
0 4
1 5
2 6
0 4
1 5
2 7
In [243]: 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. 更新
In [259]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [260]: df.iloc[0,0]=0
In [261]: df[df>2]+=1
In [262]: df
Out[262]:
a b
0 0 4
1 2 5
In [265]: df['a']=[2,1]
In [266]: df
Out[266]:
a b
0 2 4
1 1 5
In [268]: df[:]=[1,2]
In [269]: df
Out[269]:
a b
0 1 2
1 1 2
复制代码
更新数据的方式与numpy一样,索引筛选数据后直接赋值就行了,可以对所有元素赋值同一个标量,也可赋值同样形状的数据集,或是对 DataFrame 每行赋值同样的数据序列。
2. 增加
In [246]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [247]: df['c']=[5,6]
In [248]: df
Out[248]:
a b c
0 1 3 5
1 2 4 6
In [252]: df.loc[2]=-1
In [253]: df
Out[253]:
a b c
0 1 3 5
1 2 4 6
2 -1 -1 -1
In [254]: df.insert(0,'new',[0,0,0])
In [255]: 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. 删除
In [276]: df=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})
In [277]: df[df['a']>2]
Out[277]:
a b
2 3 6
In [281]: df.drop([0,2])
Out[281]:
a b
1 2 5
In [282]: df.drop('a',axis=1)
Out[282]:
b
0 4
1 5
2 6
复制代码
删除数据最灵活的方法就是通过索引筛去不需要的数据。 也可通过 drop 删除指定索引标签的数据, labels 指定要删除的标签,可以是标量或是列表, axis 参数指定查找索引标签的轴,默认为0。该方法是根据索引标签而不是位置去删除的,所以如果指定标签存在重复,这些数据会一起被删除。
4. 重构索引
In [246]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [256]: 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. 行列转置
In [133]: df=pd.DataFrame({'a':[1,2],'b':[3,4]})
In [134]: df
Out[134]:
a b
0 1 3
1 2 4
In [135]: df.T
Out[135]:
0 1
a 1 2
b 3 4
复制代码
DataFrame.T 用于实现行列转置,整个数据集将沿左上至右下的对角线翻转。 Series 调用转置方法是无效的,如果需要转置,先调用 to_frame 方法转为 DataFrame 。
6. 缺失值填充
In [95]: df=pd.DataFrame({'a':[np.nan,1,3],'b':[2,np.nan,6]})
In [96]: df
Out[96]:
a b
0 NaN 2.0
1 1.0 NaN
2 3.0 6.0
In [97]: df.fillna(0)
Out[97]:
a b
0 0.0 2.0
1 1.0 0.0
2 3.0 6.0
In [98]: df.fillna(df.mean())
Out[98]:
a b
0 2.0 2.0
1 1.0 4.0
2 3.0 6.0
In [120]: df.dropna()
Out[120]:
a b
2 3.0 6.0
In [121]: df[df.isna()]=0
In [122]: df
Out[122]:
a b
0 0.0 2.0
1 1.0 0.0
2 3.0 6.0
复制代码
fillna 方法用于直接填充缺失值,可传入标量,对所有列填充同样的值,也可传入字典或系列,对不同列填充不同的值。
dropna 方法用于直接删除带却缺失值的行或列: axis 参数指定删除行(0)或列(1); how 参数指定删除的条件, 'all' 表示全部值为NaN时删除, 'any' 表示有一个为NaN时删除; thresh 参数设置在出现几个NaN时执行删除。
isna 方法配合索引器也能对缺失值进行更新,可通过赋值标量对所有列填充同样的值,或是赋值序列对不同列填充不同的值。
六. 排序与去重
1. 直接与间接排序
In[5]: df=pd.DataFrame([[2,'a'],[1,'c'],[3,'b']],columns=['col1','col2'],index=[3,2,1])
In[6]: df
Out[6]:
col1 col2
3 2 a
2 1 c
1 3 b
In[7]: df.sort_index()
Out[7]:
col1 col2
1 3 b
2 1 c
3 2 a
In[8]: df.sort_values('col1')
Out[8]:
col1 col2
2 1 c
3 2 a
1 3 b
In [21]: 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. 去重
In[8]: df=pd.DataFrame({'a':[1,2,2,2],'b':[3,3,4,4]})
In[10]: df
Out[10]:
a b
0 1 3
1 2 3
2 2 4
3 2 4
In[11]: df.duplicated()
Out[11]:
0 False
1 False
2 False
3 True
dtype: bool
In[12]: df.drop_duplicates()
Out[12]:
a b
0 1 3
1 2 3
2 2 4
In[14]: 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 方法用于返回去重结果。 subset 和 keep 参数的作用和 duplicated 一样。
七. 乱序和抽样
1. 随机排序
In [24]: df=pd.DataFrame({'a':[1,2,3],'b':[4,5,6]})
In [25]: df.iloc[np.random.permutation(df.shape[0])]
Out[25]:
a b
1 2 5
0 1 4
2 3 6
In [27]: 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. 抽样
In [34]: df.sample(n=2) Out[34]: a b 1 2 5 2 3 6 In [36]: 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
In [13]: df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])
In [14]: df.to_csv()
Out[14]: ',a,b\nr1,1,3\nr2,2,4\n'
In [15]: df.to_csv(index=False)
Out[15]: 'a,b\n1,3\n2,4\n'
In [16]: df.to_csv("d:\\test.csv",index=False)
In [17]: df2=pd.read_csv("d:\\test.csv")
In [18]: 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 设置列数异常的坏行是否报错,默认 True , False 时会直接剔除坏行; 参数 chunksize 设置分块的大小,如果设置,会按该大小分块读取并以迭代器返回。
2. 读写excel
In [5]: df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])
In [7]: df.to_excel('d:\\test.xlsx',sheet_name='test1',index=False)
In [8]: df2=pd.read_excel('d:\\test.xlsx',sheet_name=0)
In [9]: 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 。
3. 读写sql
In [21]: 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))
In [23]: df=pd.DataFrame({'a':[1,2],'b':[3,4]},index=['r1','r2'])
In [24]: df.to_sql('test1',engine,if_exists='append',index=False)
In [25]: df.to_sql('test1',engine,if_exists='append',index=False)
In [27]: df2=pd.read_sql('select * from test1',engine)
In [28]: 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. 曲线图
In [30]: df=pd.DataFrame({'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})
In [53]: 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. 条形图
In [30]: df=pd.DataFrame({'a':[1,1.5,2.5,4],'b':[3,2.1,3.2,1],'c':[1,2,3,4]})
In [147]: 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. 直方图
In [205]: df=pd.DataFrame({'a':[1,2,2,3],'b':[3,3,3,4],'c':[1,2,3,4]})
In [210]: 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 可以绘制按列拆分为子图的直方图:
In [165]: 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. 箱线图
In [166]: df = pd.DataFrame(np.random.rand(10, 4),columns=['A','B','C','D']) In [167]: df.plot.box() Out[167]: <matplotlib.axes._subplots.AxesSubplot at 0x2aeff644080> 复制代码
5. 散点图
In[185]: df=pd.DataFrame(np.random.rand(50,3),columns=['a','b','c'])
In[186]: 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. 饼图
In [203]: df=pd.DataFrame(2*np.random.rand(3,2),index=['a','b','c'],columns=['p1','p2']) In [204]: df.plot.pie(y='p1',figsize=(4,4)) Out[204]: <matplotlib.axes._subplots.AxesSubplot at 0x2ae81f66cf8> 复制代码
In [206]: 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 指定一个列作为取值绘制饼图,二是设置参数 subplots 为 True ,会用每个列的数据绘制子图。 figsize 是绘图的通用参数,用于设置图像大小。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- [python][科学计算][numpy]使用指南
- [python][科学计算][matplotlib]使用指南
- RecyclerView使用指南(一)—— 基本使用
- RVM 使用指南
- HIVE 使用指南
- HIVE 使用指南
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
程序员2005精华本
《程序员》杂志社 / 电子工业 / 2006-1 / 45.00元
本书为集结了《程序员》杂志与《msdn开发精选》杂志精华。分上、下两册,内容包括人物&报道、管理与实践、程序员手册、年鉴、《程序员》技术专题、《msdn开发精选》文章精选等。一起来看看 《程序员2005精华本》 这本书的介绍吧!