前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Pandas进阶之数据规整化

Pandas进阶之数据规整化

作者头像
吕海峰
发布2018-04-03 15:19:46
1.8K0
发布2018-04-03 15:19:46
举报
文章被收录于专栏:BrianBrian

概述

在Pandas基本使用简单了介绍了一下Pandas的基本使用和用法,大家如果没有一点基础的同学可以先看一下那篇文章。今天我们来讲解一下Pandas的高级用法。

Numpy基本用法

在讲解Pandas高级特性之前,我们先来学习一下Numpy。Numpy是高性能计算和数据分析的基础包,一种ndarray的多维数组对象并且是一个同构的数据多维容器。创建和操作一个多维数组,我们来看一下简单的代码片段。

代码语言:javascript
复制
arr = np.arange(10,dtype=np.float32)
# np.zero,np.ones,np.empty等等

如果没有指定dtype,值得注意一点的是在后面如果要通过astype类型的话,astype是需要赋值数据的,而通过切片是不需要复制数据。切片是原始数据的一个视图,是直接映射到原始数据,对视图的任何修改也是直接映射到原始数据。如果想要复制数据,可以通过copy的包复制数据。

Numpy的布尔数组

代码语言:javascript
复制
In [17]: names = np.array(['name','bol','eric','old'])
In [18]: data = np.random.randn(4,3)
In [19]: data
Out[19]:
array([[-0.37669205,  0.0604502 ,  0.45811449],
       [ 1.04738375, -0.32027076,  1.57581797],
       [-1.30180985, -1.34583117,  0.13331215],
       [-0.43754032, -1.55706331,  0.69756061]])
In [20]: data[names=='bol']
Out[21]: array([[ 1.04738375, -0.32027076,  1.57581797]])

Python关键字中and和or在布尔数组中是无效的,如果想选取除了某个特定字段可以通过!=来选择,多个条件判断时采用&和|运算符完成。numpy.where等同于三元表达式x if condition else y的矢量化版本。

代码语言:javascript
复制
In [28]: mask = (names=='bol') | (names=='old')
In [29]: mask
Out[29]: array([False,  True, False,  True], dtype=bool)
In [30]: data[mask]
Out[30]:
array([[ 1.04738375, -0.32027076,  1.57581797],
       [-0.43754032, -1.55706331,  0.69756061]])

Numpy的切片和花式索引

Numpy的切片和花式索引完全不是一回事,很多人都混淆了概念和用法。我们先来看一下切片的用法,切片的用法和一维列表的切片也是一样的。

代码语言:javascript
复制
In [32]: data = np.arange(16).reshape(4,4)
In [33]: data
Out[33]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])
In [34]: data[:2,:1]
Out[34]:
array([[0],
       [4]])
In [35]: data[1:3,2:4]
Out[35]:
array([[ 6,  7],
       [10, 11]])

Fancy Indexing(花式索引),利用整数数组进行索引,比如:

代码语言:javascript
复制
In [38]: data[[1,2,0,3]]
Out[38]:
array([[ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [ 0,  1,  2,  3],
       [12, 13, 14, 15]])
In [39]: data[[1,2,0,3]][:,[0,3,1,2]]
Out[39]:
array([[ 4,  7,  5,  6],
       [ 8, 11,  9, 10],
       [ 0,  3,  1,  2],
       [12, 15, 13, 14]])

花式索引和切片不一样,花式索引将数据复制到新的array中。

Numpy转置和轴转换

Numpy的转置是数据重塑的一种特殊形式,它返回的是源数据的视图,可以通过transpose和T来实现,不会进行任何复制操作。

代码语言:javascript
复制
In [42]: data
Out[42]:
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

In [43]: data.T
Out[43]:
array([[ 0,  4,  8, 12],
       [ 1,  5,  9, 13],
       [ 2,  6, 10, 14],
       [ 3,  7, 11, 15]])

Numpy的唯一化表示

我们先来确定numpy的唯一化的集合,例如:

代码语言:javascript
复制
In [51]: names = np.array(['name','bol','eric','old','name','bol'])
In [52]: names
Out[52]:
array(['name', 'bol', 'eric', 'old', 'name', 'bol'],
      dtype='|S4')
In [53]: np.unique(names)
Out[53]:
array(['bol', 'eric', 'name', 'old'],
      dtype='|S4')
In [54]: data1 = np.array([2,3,5,6,7,8,1,3,6])
In [55]: np.in1d(data1,[2,6])
Out[55]: array([ True, False, False,  True, False, False, False, False,  True], dtype=bool)

  • unique(x) 计算数组中的唯一元素,并返回结果。
  • intersect1d(x,y)计算数组x和y中的公共元素,并返回有序结果。
  • union1d(x,y)计算x和y的并集,并返回结果。

这里就不一一列举,很多操作可以查看API。

Pandas的高级用法

Pandas是基于Numpy构建的,它使得数据分析工作变得更快更简单。Pandas有两种结构Series和DataFrame,他们数据表现是索引在左边,值在右边。

Pandas的Serise结构

Serise既可以看成是一个一维的numpy也可以看成是一个定长的有序字典。

代码语言:javascript
复制
In [64]: a = Series([1,2,3,4])
In [65]: b = Series(np.arange(10))
In [67]: a
Out[67]:
0    1
1    2
2    3
3    4
dtype: int64
In [68]: data = {"beijing":2300,"shanghai":2200,"shandong":2221}
In [69]: ser = Series(data)
In [70]: ser
Out[70]:
beijing     2300
shandong    2221
shanghai    2200
dtype: int64
In [75]: data1={"beijing":1100,"shanghai":2100,"tianjing":2100}
In [76]: ser2 = Series(data1)
In [84]: ser+ser2
Out[84]:
beijing     3400.0
shandong       NaN
shanghai    4300.0
tianjing       NaN
dtype: float64

Series一个最主要的特性是能自动对齐数据。

Pandas的DataFrame的数据规整化

DataFrame是一个表格型数据。

代码语言:javascript
复制
In [100]: frame
Out[100]:
    b   d   e
ut  0   1   2
oh  3   4   5
te  6   7   8
or  9  10  11
In [102]: ser = frame.iloc[0]
In [103]: frame-ser
Out[103]:
    b  d  e
ut  0  0  0
oh  3  3  3
te  6  6  6
or  9  9  9
In [105]: ser2 = Series(range(3),index=list('def'))
In [107]: frame+ser2
Out[107]:
     b     d     e   f
ut NaN   1.0   3.0 NaN
oh NaN   4.0   6.0 NaN
te NaN   7.0   9.0 NaN
or NaN  10.0  12.0 NaN

将函数应用到各行或各列是通过apply方法实现

DataFrame的列(columns)合并

当多个数据集进行合并(merge)和连接(join)都是通过一个或者多个键连接起来,多个DataFrame的合并操作是通过pandas.merge来实现的。DataFrame的合并有多种连接方式,merge默认采用inner连接方式。还有left,right以及outer连接。外连接求取的是键的并集,组合了左连接和右连接。

代码语言:javascript
复制
In [15]: df1 = DataFrame({'key':list('bbacaab'),'data1':range(7)})
In [16]: df2 = DataFrame({'key':list('abd'),'data2':range(3)})
In [17]: pd.merge(df1,df2)====pd.merge(df1,df2,on='key')
Out[17]:
   data1 key  data2
0      0   b      1
1      1   b      1
2      6   b      1
3      2   a      0
4      4   a      0
5      5   a      0
In [18]: pd.merge(df1,df2,how='outer')
Out[18]:
   data1 key  data2
0    0.0   b    1.0
1    1.0   b    1.0
2    6.0   b    1.0
3    2.0   a    0.0
4    4.0   a    0.0
5    5.0   a    0.0
6    3.0   c    NaN
7    NaN   d    2.0

这是一种多对一的合并,df1中有多个被标记的数据行(a和b),而df2中key的列的每个值而仅对应一个,这时候调用merge即可,也可以通过on来指定重叠的列名。如果两个dataframe的key不一样,可以分别指定。

代码语言:javascript
复制
In [27]: df1 = DataFrame({'lkey':list('bbacaab'),'data1':range(7)})
In [28]: df2 = DataFrame({'rkey':list('abd'),'data2':range(3)})
In [29]: pd.merge(df1,df2,left_on='lkey',right_on='rkey')
Out[29]:
   data1 lkey  data2 rkey
0      0    b      1    b
1      1    b      1    b
2      6    b      1    b
3      2    a      0    a
4      4    a      0    a
5      5    a      0    a

如果是一种多对多的合并,比如如下格式:

代码语言:javascript
复制
In [34]: df1 = DataFrame({'key':list('bbacaab'),'data1':range(7)})
In [35]: df2 = DataFrame({'key':list('ababd'),'data2':range(5)})
In [36]: pd.merge(df1,df2,on='key',how='left')
Out[36]:
    data1 key  data2
0       0   b    1.0
1       0   b    3.0
2       1   b    1.0
3       1   b    3.0
4       2   a    0.0
5       2   a    2.0
6       3   c    NaN
7       4   a    0.0
8       4   a    2.0
9       5   a    0.0
10      5   a    2.0
11      6   b    1.0
12      6   b    3.0
In [37]: pd.merge(df1,df2,on='key',how='right')
Out[37]:
    data1 key  data2
0     0.0   b      1
1     1.0   b      1
2     6.0   b      1
3     0.0   b      3
4     1.0   b      3
5     6.0   b      3
6     2.0   a      0
7     4.0   a      0
8     5.0   a      0
9     2.0   a      2
10    4.0   a      2
11    5.0   a      2
12    NaN   d      4
In [38]: pd.merge(df1,df2,on='key')
Out[38]:
    data1 key  data2
0       0   b      1
1       0   b      3
2       1   b      1
3       1   b      3
4       6   b      1
5       6   b      3
6       2   a      0
7       2   a      2
8       4   a      0
9       4   a      2
10      5   a      0
11      5   a      2
In [39]: pd.merge(df1,df2,on='key',how='outer')
Out[39]:
    data1 key  data2
0     0.0   b    1.0
1     0.0   b    3.0
2     1.0   b    1.0
3     1.0   b    3.0
4     6.0   b    1.0
5     6.0   b    3.0
6     2.0   a    0.0
7     2.0   a    2.0
8     4.0   a    0.0
9     4.0   a    2.0
10    5.0   a    0.0
11    5.0   a    2.0
12    3.0   c    NaN
13    NaN   d    4.0

多对多产生的是行的笛卡尔积,如果要按照多个column进行合并可以通过on=[‘key1’,’key2’]

DataFrame的索引合并

DataFrame中的连接键位于其索引中,这种情况需要传入left_index=True和right_index=True来说明连接的键,对于层次化的数据多个键合并时,按需通过left_on或者right_on=[‘key1’,’key2’]来合并。

代码语言:javascript
复制
In [57]: left1 = DataFrame({'key':list('abaabc'),'value':range(6)})
In [58]: right1 = DataFrame({'group_val':[3.5,7]},index=list('ab'))
In [59]: right1
Out[59]:
   group_val
a        3.5
b        7.0
In [60]: left1
Out[60]:
  key  value
0   a      0
1   b      1
2   a      2
3   a      3
4   b      4
5   c      5
In [61]: pd.merge(left1,right1,left_on='key',right_index=True)
Out[61]:
  key  value  group_val
0   a      0        3.5
2   a      2        3.5
3   a      3        3.5
1   b      1        7.0
4   b      4        7.0

对于索引的合并,建议采用join的方式来进行合并。

代码语言:javascript
复制
In [73]: left1 = DataFrame({'key':list('abaabc'),'value':range(6)},index=list('abcdef'))
In [74]: right1 = DataFrame({'val':[3.5,7]},index=list('de'))
In [75]: an = DataFrame({'val':[3.5,7]},index=list('de'))
In [79]: left1.join([right1,an])
Out[79]:
  key  value  group_val  val
a   a      0        3.5  NaN
b   b      1        7.0  NaN
c   a      2        NaN  NaN
d   a      3        NaN  3.5
e   b      4        NaN  7.0
f   c      5        NaN  NaN
DataFrame的轴向连接
代码语言:javascript
复制
In [86]: s1 = Series(data=[1,2,3],index=list('abc'))
In [87]: s2 = Series([1,2],index=list('de'))
In [88]: s3 = Series([3,4],index=list('fg'))
In [89]: pd.concat([s1,s2,s3],axis=0)
Out[89]:
a    1
b    2
c    3
d    1
e    2
f    3
g    4
dtype: int64
In [90]: pd.concat([s1,s2,s3],axis=1)
Out[90]:
     0    1    2
a  1.0  NaN  NaN
b  2.0  NaN  NaN
c  3.0  NaN  NaN
d  NaN  1.0  NaN
e  NaN  2.0  NaN
f  NaN  NaN  3.0
g  NaN  NaN  4.0
In [96]: s4=pd.concat([s1*5,s3])
In [97]: s4
Out[97]:
a     5
b    10
c    15
f     3
g     4
dtype: int64
In [98]: pd.concat([s1,s4],axis=1,join='inner')
Out[98]:
   0   1
a  1   5
b  2  10
c  3  15
In [99]: pd.concat([s1,s4],axis=1,join_axes=[['a','b','c']])
Out[99]:
   0   1
a  1   5
b  2  10
c  3  15

也可以通过join方式来指定inner或者outer来获取交集和并集,你也可以通过join_axes指定其他轴上的索引。 在concat之后结果区分不开,如何让他区分开结果?可以通过keys来实现,比如:

代码语言:javascript
复制
In [104]: result = pd.concat([s1,s4],join='inner',keys=['one','two'])
Out[104]:
one  a     1
     b     2
     c     3
two  a     5
     b    10
     c    15
     f     3
     g     4
dtype: int64
In [108]: result.unstack()
Out[108]:
       a     b     c    f    g
one  1.0   2.0   3.0  NaN  NaN
two  5.0  10.0  15.0  3.0  4.0
In [105]: result1 = pd.concat([s1,s4],axis=1,join='inner',keys=['one','two'])
Out[105]:
   one  two
a    1    5
b    2   10
c    3   15
In [109]: result1.unstack()
Out[109]:
one  a     1
     b     2
     c     3
two  a     5
     b    10
     c    15
dtype: int64

这样可以把一个Series结构轻松的转化为DataFrame结构来处理,可以相互的转换。对于DataFrame结构也可以通过concat来合并数据。如果两个数据集的索引存在重叠怎么办?可以通过combine——frist进行打补丁。

DataFrame的重塑和轴向旋转

stack:将数据的列旋转为行,默认会过滤掉缺失的数据,该运算是可逆的。 unstack:将数据的行旋转为列,操作是最内层的,传入分层级别或者名称。

代码语言:javascript
复制
In [23]: data = DataFrame(np.arange(6).reshape((2,3)),index=pd.Index(['Co','Ho'],name='state'),columns=pd.Index(['one','two','three'],name
    ...: ='number'))
In [24]: data
Out[24]:
number  one  two  three
state
Co        0    1      2
Ho        3    4      5
In [25]: result = data.stack()
Out[25]:
state  number
Co     one       0
       two       1
       three     2
Ho     one       3
       two       4
       three     5
dtype: int64
In [28]: result.unstack()
Out[28]:
number  one  two  three
state
Co        0    1      2
Ho        3    4      5
In [30]: result.unstack('state')
Out[30]:
state   Co  Ho
number
one      0   3
two      1   4
three    2   5

通过stack() 将列数据转换为行,转化为了一个层次化Series。对一个多层次化的Series可以通过unstack()**转化为DataFrame结构。

代码语言:javascript
复制
In [6]: s1=Series(xrange(4),index=list('abcd'))
In [7]: s2=Series(range(4,7,1),index=list('cde'))
In [8]: pd.concat([s1,s2],keys=['one','two'])
Out[8]:
one  a    0
     b    1
     c    2
     d    3
two  c    4
     d    5
     e    6
dtype: int64
In [10]: pd.concat([s1,s2],keys=['one','two']).unstack()
Out[10]:
       a    b    c    d    e
one  0.0  1.0  2.0  3.0  NaN
two  NaN  NaN  4.0  5.0  6.0
In [19]: result.unstack().stack(dropna=False)
Out[19]:
one  a    0.0
     b    1.0
     c    2.0
     d    3.0
     e    NaN
two  a    NaN
     b    NaN
     c    4.0
     d    5.0
     e    6.0
dtype: float64

数据转换

去重

在通过Pandas处理一些数据时,另一个比较重要的是过滤、清洗以及转换。

代码语言:javascript
复制
In [27]: data = DataFrame({'one':['a']*3+['b']*4,'two':[1,1,2,3,3,4,4]})
In [28]: data
Out[28]:
  one  two
0   a    1
1   a    1
2   a    2
3   b    3
4   b    3
5   b    4
6   b    4

在上面的数据中会有一些重复的数据,我们需要过滤掉。

代码语言:javascript
复制
In [34]: data.duplicated()
Out[34]:
0    False
1     True
2    False
3    False
4     True
5    False
6     True
dtype: bool
In [35]: data.drop_duplicates()
Out[35]:
  one  two
0   a    1
2   a    2
3   b    3
5   b    4
In [36]: data.drop_duplicates(['two'])
Out[36]:
  one  two
0   a    1
2   a    2
3   b    3
5   b    4
```,或者也可以指定去除重复的列。
**duplicated**返回的是各行是否重复布尔值,或者你也可以通过**drop_duplicates**方法去除重复,或者也可以指定去除重复的列。
#### 面元
所谓的面元(bin)亦称为离散化。
```python
In [52]: ages = np.random.randint(100,size=20)

In [53]: ages
Out[53]:
array([50, 99, 37, 90,  9, 33, 26, 34, 97, 75, 46, 44, 17, 23, 15, 25, 63,
        8, 39, 54])
In [57]: bins = [0,18,25,35,60,100]
In [58]: cats = pd.cut(ages,bins)
In [59]: cats
Out[59]:
[(35, 60], (60, 100], (35, 60], (60, 100], (0, 18], ..., (18, 25], (60, 100], (0, 18], (35, 60], (35, 60]]
Length: 20
Categories (5, interval[int64]): [(0, 18] < (18, 25] < (25, 35] < (35, 60] < (60, 100]]
In [60]: cats.value_counts()
Out[60]:
(0, 18]      4
(18, 25]     2
(25, 35]     3
(35, 60]     6
(60, 100]    5
dtype: int64

可以有效的处理,还可以通过left/right参数来左右开关闭区间,precision设置小数位数。qcut是对样本进行分位数。

异常值检测

检查超过3或者-3的异常值

代码语言:javascript
复制
data = DataFrame(np.random.randn(1000,4))
#检查超过3或者-3的异常值
In [78]: data[(np.abs(data)>3).any(1)]
Out[78]:
            0         1         2         3
46  -0.658090 -0.207434  3.525865  0.283070
67   0.599947 -3.645860  0.255475 -0.549574
289 -1.559625  0.336788 -3.333767 -1.240685
371 -1.116332 -3.018842 -0.298748  0.406954
396 -3.108915  1.117755 -0.152780 -0.340173
526  1.188742 -3.183867  1.050471 -1.042736
573 -2.214074 -3.140963 -1.509976 -0.389818
738 -0.088202  1.090038 -0.848098 -3.194414
768  0.474358  0.003349 -0.011807  3.023720
797  2.368010  0.452649 -3.481593  0.789944
966  0.164293  3.082067 -0.516982  0.251909
994 -0.843849  3.189940  0.070978  0.516982
#然后可以通过将超过三的值设置到-3到3之间
In [83]: data[(np.abs(data)>3)]=np.cos(data)*3
In [84]: data[(np.abs(data)>3).any(1)]
Out[84]:
Empty DataFrame
Columns: [0, 1, 2, 3]
Index: []
哑变量

在数据挖掘或者统计学习里面,我们需要将分类变量转换为dummy matrix或者indicator matrix

代码语言:javascript
复制
In [86]: data = DataFrame({'key':list('bbaabc'),'num':range(6)})
In [87]: data
Out[87]:
  key  num
0   b    0
1   b    1
2   a    2
3   a    3
4   b    4
5   c    5
In [88]: pd.get_dummies(data['key'])
Out[88]:
   a  b  c
0  0  1  0
1  0  1  0
2  1  0  0
3  1  0  0
4  0  1  0
5  0  0  1
In [89]: pd.get_dummies(data['num'])
Out[89]:
   0  1  2  3  4  5
0  1  0  0  0  0  0
1  0  1  0  0  0  0
2  0  0  1  0  0  0
3  0  0  0  1  0  0
4  0  0  0  0  1  0
5  0  0  0  0  0  1
In [94]: values = np.random.rand(10)
In [95]: values
Out[95]:
array([ 0.47712303,  0.14542606,  0.91058923,  0.77642134,  0.92337761,
        0.50655742,  0.77692242,  0.26667882,  0.94795336,  0.63819667])
In [96]: bins = [0,0.2,0.4,0.6,0.8,1.0]
In [97]: pd.get_dummies(pd.cut(values,bins))
Out[97]:
   (0.0, 0.2]  (0.2, 0.4]  (0.4, 0.6]  (0.6, 0.8]  (0.8, 1.0]
0           0           0           1           0           0
1           1           0           0           0           0
2           0           0           0           0           1
3           0           0           0           1           0
4           0           0           0           0           1
5           0           0           1           0           0
6           0           0           0           1           0
7           0           1           0           0           0
8           0           0           0           0           1
9           0           0           0           1           0

参考书籍

1.《Python 数据分析》 2.《Python数据挖掘与分析》 3.《利用Python进行数据分析》

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • Numpy基本用法
    • Numpy的布尔数组
      • Numpy的切片和花式索引
        • Numpy转置和轴转换
          • Numpy的唯一化表示
          • Pandas的高级用法
            • Pandas的Serise结构
              • Pandas的DataFrame的数据规整化
                • 数据转换
                • 检查超过3或者-3的异常值
                  • 参考书籍
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档