pandas数据大发888平台出租规整化:清理、转换、合并、重塑

数据分析和大发888平台出租 haozbbs.com Q1446595067建模方面的大量编程工作都是用在数据准备上的:加载、清理、转换以及重塑。
许多人选择使用通用编程语言或unix文本处理工具(如sed或awk)对数据格式进行专门处理。

幸运的是,pandas和python标准库提供了一组高级的、灵活的、高效的核心函数和算法,将数据规整化正确的形式。

  1. 合并数据集:

pandas对象中的数据可以通过一些内置的方式进行合并:
(1)pandas.merge可根据一个名多个键将不同DataFrame中的行连接起来。sql关系型数据库也有merge法,它是用merge实现的就是数据库的连接操作(inner内连接交集,outer外连接,左连接,右连接=>并集)。
(2)pandas.concat可以沿着一条轴将多个对象堆叠到一起。

(3)实例方法combine_first可以将重复数据编接在一起,用一个对象中的值填充另一个对象中的缺失值。

下面分别讲解这些方法:

数据库风格的DataFrame合并:

数据集的合并(merge)或连接(join)运算是通过一个或多个键将行连接起来的。这些运算是关系型数据库的核心。

pandas的merge函数是对数据应用这些算法的主要切入点。

(1)merge的用法

import pandas as pd
import numpy as np
from pandas import Series,DataFrame

df1=DataFrame({'key':['b','b','a','c','a','a','b'],
               'data1':range(7)})
df2=DataFrame({'key':['a','b','d'],
               'data2':range(3)})
print df1
#输出结果如下:
#    data1 key
# 0      0   b
# 1      1   b
# 2      2   a
# 3      3   c
# 4      4   a
# 5      5   a
# 6      6   b
# print df2
# #输出结果如下:
#    data2 key
# 0      0   a
# 1      1   b
# 2      2   d
(1)这是一种多对一的合并:df1中的数据有多个被标记为a和b行,而df2中key列的每个值则仅对应一行。
    这些对象调用merge即可得到
print pd.merge(df1,df2)
#输出结果如下:
#    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
# #注意:上面的例子并没有指明要用哪个列进行连接。如果没有指定,merge就会将重叠列的列名当做键。
(2)下面指定列:用能数on=
# print pd.merge(df1,df2,on='key') #输出结果与上面一样

(3)如果两个对象的列名不同,也可以分别进行指定:left_on,right_on
df3=DataFrame({'lkey':['b','b','a','c','a','a','b'],
               'data1':range(7)})
df4=DataFrame({'rkey':['a','b','d'],
               'data2':range(3)})
print pd.merge(df3,df4,left_on='lkey',right_on='rkey')
#输出结果如下:
#    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
#
#注意:结果里面c和d以及与之相关的数据消失了。默认情况下,merge做的是"inner"连接:结果中的键是交集。
#     而其它外连接left,right,outer求取的是键的并集,组合了左连接和右连接的效果。
(4) outer外连接:并集,两个数据Key都要
# print pd.merge(df1,df2,how='outer')  #外连接,两边的key都要传入
# #输出结果如下:并集,df1,df2所有的值都放入
# #    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

(5) left左连接:并集,左连接是以左边的为主
# print pd.merge(df1,df2,on='key',how='left') #左连接
# #输出结果如下:  左连接是以左边的为主,即df1为主,顾只有df1的key
# #    data1 key  data2
# # 0      0   b    1.0
# # 1      1   b    1.0
# # 2      2   a    0.0
# # 3      3   c    NaN
# # 4      4   a    0.0
# # 5      5   a    0.0
# # 6      6   b    1.0

(6)right右连接:并集,右连接是以右边的为主
# print pd.merge(df1,df2,how='right')  #右连接
# #输出结果如下:右连接,以df2的为主,顾只有df2的key,其它的值是全部写入
# #    data1 key  data2
# # 0    0.0   b      1
# # 1    1.0   b      1
# # 2    6.0   b      1
# # 3    2.0   a      0
# # 4    4.0   a      0
# # 5    5.0   a      0
# # 6    NaN   d      2

(7)inner内连接:交集,默认就是内连接
# print pd.merge(df1,df2,how='inner') #即merge默认情况下是inner,inner是交集
# #输出结果如下:取df1,df2都有key
# #    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

(8)若多个键要进行合并,传入一个由列名组成的列表即可
left=DataFrame({'key1':['foo','foo','bar'],
                'key2':['one','two','one'],
                'lval':[1,2,3]})
right=DataFrame({'key1':['foo','foo','bar','bar'],
                 'key2':['one','one','one','two'],
                 'rval':[4,5,6,7]})
print left
#输出结果如下:
#   key1 key2  lval
# 0  foo  one     1
# 1  foo  two     2
# 2  bar  one     3
print right
#输出结果如下:
#   key1 key2  rval
# 0  foo  one     4
# 1  foo  one     5
# 2  bar  one     6
# 3  bar  two     7
print pd.merge(left,right,on=['key1','key2'],how='outer')
#输出结果如下:看key1,key2两个键对应的lval的值。外连接,即所有的key都要。
#right中的key组合[foo,one],[foo,one],[foo,two]...用right的key看left有没有。
#   key1 key2  lval  rval
# 0  foo  one   1.0   4.0
# 1  foo  one   1.0   5.0
# 2  foo  two   2.0   NaN
# 3  bar  one   3.0   6.0
# 4  bar  two   NaN   7.0

(9)合并运算需要考虑对重复列名的处理,merge有一个实用的suffixes选项,用于指定附加到左右两个DataFrame对象的重叠列名上的字符串。
print pd.merge(left,right,on='key1') #只用单个key,它就有单个key1分别和left,right的key2的组合
#输出结果如下:
#   key1 key2_x  lval key2_y  rval
# 0  foo    one     1    one     4
# 1  foo    one     1    one     5
# 2  foo    two     2    one     4
# 3  foo    two     2    one     5
# 4  bar    one     3    one     6
# 5  bar    one     3    two     7
print pd.merge(left,right,on='key1',suffixes=('_left','_right'))
#输出结果如下:
#   key1 key2_left  lval key2_right  rval
# 0  foo       one     1        one     4
# 1  foo       one     1        one     5
# 2  foo       two     2        one     4
# 3  foo       two     2        one     5
# 4  bar       one     3        one     6
# 5  bar       one     3        two     7

merger函数的参数
参数 说明
left 参与合并的左侧DataFrame
right 参与合并的右侧DataFrame
how “inner”、“outer”、“left”、“right”其中之一。默认为"inner"(交集),其它为并集
on 用于连接的列名。必须存在于左右两个DataFrame对象中。如果未指定,且其它连接键也未指定,由以
left和right列名的交集作为连接键
left_on 左侧DataFrame中用作连接键的列
right_on 右侧DataFrame中用作连接键的列
left_index 将左侧的行索引用作其连接键
righgt_index 将右侧的行索引用作其连接键
sort 根据连接键对合并后的数据进行排序,默认为True.有时处理大数据集时,禁用该选项可获得更好的性能
suffixes 字符串值元组,用于追加到重叠列名的末尾,默认为('_x','_y').
copy 设置为False,可以在某些特殊情况下避免将数据复制到结果数据结构中。默认总是复制。

索引上DataFrame的合并:

DataFrame中的连接键位于其索引中。在这种情况下,可以传入left_index=True或right_index=True(或两个都传)

以说明索引应该被用作连接键。

(1)merge的用法:索引上合并用left_index=True、right_index=True

import pandas as pd
import numpy as np
from pandas import Series,DataFrame

(1)DataFrame中的连接键位于其索引中:left_index=True或right_index=True(或两个都传)来说明索引应该被用作连接键。
left1=DataFrame({'key':['a','b','a','a','b','c'],
                 'value':range(6)})
right1=DataFrame({'group_val':[3.5,7]},index=['a','b'])
print left1
#输出结果如下:
#   key  value
# 0   a      0
# 1   b      1
# 2   a      2
# 3   a      3
# 4   b      4
# 5   c      5
print right1
#输出结果如下:
#    group_val
# a        3.5
# b        7.0
print pd.merge(left1,right1,left_on='key',right_index=True)
#输出结果如下:
#   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

(2)由于默认的merge方法是求取连接键的交集,因此可以通过外连接的方式得到它们的并集。how='outer'
print pd.merge(left1,right1,left_on='key',right_index=True,how='outer')
#输出结果如下:
#   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
# 5   c      5        NaN

(3)层次化索引,多层行/列索引
lefth=DataFrame({'key1':['Ohio','Ohio','Ohio','Nevada','Nevada'],
                 'key2':[2000,2001,2002,2001,2002],
                 'data':np.arange(5.)})
righth=DataFrame(np.arange(12).reshape(6,2),
                 index=[['Nevada','Nevada','Ohio','Ohio','Ohio','Ohio'],
                 [2001,2000,2000,2000,2001,2002]],
                 columns=['event1','event2'])
print lefth
#输出结果如下:
#    data    key1  key2
# 0   0.0    Ohio  2000
# 1   1.0    Ohio  2001
# 2   2.0    Ohio  2002
# 3   3.0  Nevada  2001
# 4   4.0  Nevada  2002
print righth
#输出结果如下:
#              event1  event2
# Nevada 2001       0       1
#        2000       2       3
# Ohio   2000       4       5
#        2000       6       7
#        2001       8       9
#        2002      10      11
#必须以列表的形式指明用作合并键的多个列(注意对重复索引值的处理)
#left_on左侧DataFrame作为连接键,即lefth,而索引是right_index,即右侧数据为行索引即righth的行索引为行索引
print pd.merge(lefth,righth,left_on=['key1','key2'],right_index=True)
#没有how参数,默认是inner连接,即交集,取lefth的['key1','key2']的数据与righth的行有交集,即相同的取出
#输出结果如下:
#    data    key1  key2  event1  event2
# 0   0.0    Ohio  2000       4       5
# 0   0.0    Ohio  2000       6       7
# 1   1.0    Ohio  2001       8       9
# 2   2.0    Ohio  2002      10      11
# 3   3.0  Nevada  2001       0       1

#(4)外连接:how='outer' 并集
print pd.merge(lefth,righth,left_on=['key1','key2'],right_index=True,how='outer')
#输出结果如下:
#    data    key1  key2  event1  event2
# 0   0.0    Ohio  2000     4.0     5.0
# 0   0.0    Ohio  2000     6.0     7.0
# 1   1.0    Ohio  2001     8.0     9.0
# 2   2.0    Ohio  2002    10.0    11.0
# 3   3.0  Nevada  2001     0.0     1.0
# 4   4.0  Nevada  2002     NaN     NaN
# 4   NaN  Nevada  2000     2.0     3.0

#(5)用merge同时使用合并双方的索引
left2=DataFrame([[1.,2.],[3.,4.],[5.,6.]],index=['a','c','e'],
                columns=['Ohio','Nevada'])
right2=DataFrame([[7.,8.],[9.,10.],[11.,12.],[13,14]],
                 index=['b','c','d','e'],columns=['Missouri','Alabama'])
print left2
#输出结果如下:
#    Ohio  Nevada
# a   1.0     2.0
# c   3.0     4.0
# e   5.0     6.0
print right2
#输出结果如下:
#    Missouri  Alabama
# b       7.0      8.0
# c       9.0     10.0
# d      11.0     12.0
# e      13.0     14.0
print pd.merge(left2,right2,how='outer',left_index=True,right_index=True)
#同时使用了left_index,right_index同时合并双方索引,且outer外连接交集
#输出结果如下:
#    Ohio  Nevada  Missouri  Alabama
# a   1.0     2.0       NaN      NaN
# b   NaN     NaN       7.0      8.0
# c   3.0     4.0       9.0     10.0
# d   NaN     NaN      11.0     12.0
# e   5.0     6.0      13.0     14.0

(2)join的用法:索引上合并用left_index=True、right_index=True

DataFrame的一个实例方法Join:更为方便地实现按索引合并。它还可以用于合并多个带有相同或相似索引的DataFrame对象,而不管它们之间有没有重叠的列。

#Join:在连接键上是做左连接
# (1)DataFrame的一个实例方法Join:更为方便地实现按索引合并。不管它们之间有没有重叠的列。
#上面的例子可以编写如下:
print left2.join(right2,how='outer')  #类似python的字符串连接Join
#输出结果如下:
#    Ohio  Nevada  Missouri  Alabama
# a   1.0     2.0       NaN      NaN
# b   NaN     NaN       7.0      8.0
# c   3.0     4.0       9.0     10.0
# d   NaN     NaN      11.0     12.0
# e   5.0     6.0      13.0     14.0

# (2)它还支持DataFrame的索引跟调用者DataFrame的某个列之间的连接(即第一个DataFrame的行索引与第二个DataFrame的列连接)
print left1.join(right1,on='key')
#输出结果如下:
#   key  value  group_val
# 0   a      0        3.5
# 1   b      1        7.0
# 2   a      2        3.5
# 3   a      3        3.5
# 4   b      4        7.0
# 5   c      5        NaN

#(3)可以向join传入一组DataFrame
another=DataFrame([[7.,8.],[9.,10.],[11.,12.],[16.,17.]],
                 index=['a','c','e','f'],columns=['New York','Oregon'])
print another
#输出结果如下:
#    New York  Oregon
# a       7.0     8.0
# c       9.0    10.0
# e      11.0    12.0
# f      16.0    17.0
print left2.join([right2,another]) #left2左分别连接right2,another
# left2内容如下:
# #    Ohio  Nevada
# # a   1.0     2.0
# # c   3.0     4.0
# # e   5.0     6.0
# right2内容如下:
# #    Missouri  Alabama
# # b       7.0      8.0
# # c       9.0     10.0
# # d      11.0     12.0
# # e      13.0     14.0
#left2.join([right2,another])输出结果如下:
#    Ohio  Nevada  Missouri  Alabama  New York  Oregon
# a   1.0     2.0       NaN      NaN       7.0     8.0
# c   3.0     4.0       9.0     10.0       9.0    10.0
# e   5.0     6.0      13.0     14.0      11.0    12.0

轴上连接:

另一种数据合并运算也被称作连接、绑定或堆叠。numpy有一个用于合并原始Numpy数组的concatenation函数。concatenate是Numpy的方法,

而concate是pandas的方法。

concatenate连接:

arr=np.arange(12).reshape((3,4))
print arr
#输出的结果如下:
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
print np.concatenate([arr,arr],axis=1) #axis=1是列
#输出的结果如下:
# [[ 0  1  2  3  0  1  2  3]
#  [ 4  5  6  7  4  5  6  7]
#  [ 8  9 10 11  8  9 10 11]]

concate连接:

# 如果各对象其他轴上的索引不同,那些轴应该是做并集还是交集?
# 结果对象中的分组需要各不相同吗?
# 用于连接的轴axis重要吗?

concate用于解决上面的三个问题,它与concatenate没多大区别,只是多了一些参数

(1)三个没有重叠索引的Series,对这些对象调用concat可以将值和索引粘合在一起
s1=Series([0,1],index=['a','b'])
s2=Series([2,3,4],index=['c','d','e'])
s3=Series([5,6],index=['f','g'])
print s1
# a    0
# b    1
print s2
# c    2
# d    3
# e    4
print s3
# f    5
# g    6
print pd.concat([s1,s2,s3])
#输出结果如下:
# a    0
# b    1
# c    2
# d    3
# e    4
# f    5
# g    6

(2)默认情况下,concat是在axix=0行上作用的,最终产生一个新的Series.如果传入axis=1,则结果就会变成一个DataFrame(axis=1是列)
#series行向合并,本来series只有行索引,故产生一个新的Series.如果列合并,有几个数组,列不一定相同,所以会产生一个DataFrame
print pd.concat([s1,s2,s3],axis=1)
#输出结果如下:
#      0    1    2
# a  0.0  NaN  NaN
# b  1.0  NaN  NaN
# c  NaN  2.0  NaN
# d  NaN  3.0  NaN
# e  NaN  4.0  NaN
# f  NaN  NaN  5.0
# g  NaN  NaN  6.0

(3)这种情况下,另外一条轴上没有重叠,从索引的有序并集上就可以看出。。传入join='inner'即可得到它们的交集
s4=pd.concat([s1*5,s3])
print pd.concat([s1,s4],axis=1)
#输出结果如下:
#      0  1
# a  0.0  0
# b  1.0  5
# f  NaN  5
# g  NaN  6
print pd.concat([s1,s4],axis=1,join='inner')
#输出结果如下:
#    0  1
# a  0  0
# b  1  5

(4)可以通过join_axes指字要在其他轴上使用的索引
print pd.concat([s1,s4],axis=1,join_axes=[['a','c','b','e']])
#输出结果如下:
#      0    1
# a  0.0  0.0
# c  NaN  NaN
# b  1.0  5.0
# e  NaN  NaN

(5)不过有个问题,参与连接的片段在结果中区分不开。假设你想要在连接轴上创建一个层次化索引。使用keys参数即可达到目的
result=pd.concat([s1,s1,s3],keys=['one','two','three'])
print result
#输出结果如下:
# one    a    0
#        b    1
# two    a    0
#        b    1
# three  f    5
#        g    6
# dtype: int64
print result.unstack()
#输出结果如下:
#          a    b    f    g
# one    0.0  1.0  NaN  NaN
# two    0.0  1.0  NaN  NaN
# three  NaN  NaN  5.0  6.0

(6)如果沿着axis=1对Series进行合并,则keys就会成为DataFrame的列头
print pd.concat([s1,s2,s3],axis=1,keys=['one','two','three'])
#输出结果如下:
#    one  two  three
# a  0.0  NaN    NaN
# b  1.0  NaN    NaN
# c  NaN  2.0    NaN
# d  NaN  3.0    NaN
# e  NaN  4.0    NaN
# f  NaN  NaN    5.0
# g  NaN  NaN    6.0

(7)同样的逻辑对DataFrame对象也是一样:
df1=DataFrame(np.arange(6).reshape(3,2),index=['a','b','c'],
              columns=['one','two'])
df2=DataFrame(5+np.arange(4).reshape(2,2),index=['a','c'],
              columns=['three','four'])
print pd.concat([df1,df2],axis=1,keys=['level1','level2'])
#输出结果如下:
#   level1     level2
#      one two  three four
# a      0   1    5.0  6.0
# b      2   3    NaN  NaN
# c      4   5    7.0  8.0

(8)如果传入的不是列表而是一个字典,则字黄的键就会被做Keys选项的值。
print pd.concat({'level1':df1,'level2':df2},axis=1)
#   level1     level2
#      one two  three four
# a      0   1    5.0  6.0
# b      2   3    NaN  NaN
# c      4   5    7.0  8.0

(9)此外还有两个用于管理层次化索引创建方式的参数:
  a:key,names
print pd.concat([df1,df2],axis=1,keys=['level1','level2'],
                names=['upper','lower'])
#输出的结果如下:
# upper level1     level2
# lower    one two  three four
# a          0   1    5.0  6.0
# b          2   3    NaN  NaN
# c          4   5    7.0  8.0

  b:ignore_index=True
df1=DataFrame(np.random.randn(3,4),columns=['a','b','c','d'])
df2=DataFrame(np.random.randn(2,3),columns=['b','d','a'])
print df1
print df2
#在这种情况下,传入ignore_index=True即可:
print pd.concat([df1,df2],ignore_index=True)
#输出结果如下:
#           a         b         c         d
# 0 -0.540071 -0.225394 -0.851317 -1.638987
# 1  0.163700  1.375732  0.255257  1.290061
# 2  0.787074  0.137692  0.929145 -0.793582
# 3 -0.502263  0.717226       NaN -1.224583
# 4 -0.023067 -0.556030       NaN -0.819273

concat函数的参数
参数 说明
objs 参与连接的pandas对象的列表或字典。唯一必需的参数
axis 指明连接的轴向,默认为0
join “inner”、“outer”其中之一,默认为"outer".指明其他轴向上的索引是按交集(inner)
还是并集(outer)进行合并
join_axes 指明用于其他n-1条轴的索引,不执行并集/交集运算
keys 与连接对象有关的值,用于形成连接轴向上的层次化索引。可以是任意值的列表或数组、元组数组、
数组列表(如果将levels设置成多级数组的话)
levels 指定用作层次化索引各级别上的索引,如果设置了keys的话
names 用于创建分层级别的名称,如果设置了keys和levels的话
verify_integrity 检查结果对象新轴上的重复情况,如果发现则引发异常。默认(False)允许重复
ignore_index 不保留连接轴上的索引,产生一组新索引

合并重叠数据:numpy.where, pd.combine_first

还有一种数据组合问题不能用简单的合并(merge)或连接(concatenation)运算来处理。

比如,可能有索引全部或部分重叠的两个数据集。我们使用Numpy的where函数,它用于表达一种矢量化的if-else:

(1)Numpy的where

import pandas as pd
import numpy as np
from pandas import Series,DataFrame

(1)Numpy的where
a=Series([np.nan,2.5,np.nan,3.5,4.5,np.nan],
         index=['f','e','d','c','b','a'])
b=Series(np.arange(len(a),dtype=np.float64),
         index=['f','e','d','c','b','a'])
b[-1]=np.nan
print a
#输出结果如下:
# f    NaN
# e    2.5
# d    NaN
# c    3.5
# b    4.5
# a    NaN
print b
#输出结果如下:
# f    0.0
# e    1.0
# d    2.0
# c    3.0
# b    4.0
# a    NaN
print np.where(pd.isnull(a),b,a) #a如果是Nan,则用b的数据代替,否则还是a的值
#输出结果如下:
# [ 0.   2.5  2.   3.5  4.5  nan]

(2)Series有一个combine_first方法,可以实现上面一样的功能,而且会时行数据对齐

print b[:-2].combine_first(a[2:]) #b[:-2]的值若有nan则用a[2:]的值代替。但是b[:-2]是不包括右边的倒数第二个b的,
# 则b的值用第一个4.5
#输出结果如下:
# a    NaN
# b    4.5
# c    3.0
# d    2.0
# e    1.0
# f    0.0
#Series的combine_first方法实例:DataFrame也有combine_first方法
s1=pd.Series([1,np.nan])
s2=pd.Series([3,4])
print s1
# 0    1.0
# 1    NaN
print s2
# 0    3
# 1    4
print s1.combine_first(s2) #s1里有nan就换成s2的值
# 0    1.0
# 1    4.0

(3)DataFrame的combine_first也是同上,因此可以将其看做:用参数对象中的数据为调用者对象的缺失数据"打补丁"

df1=DataFrame({'a':[1.,np.nan,5.,np.nan],
               'b':[np.nan,2.,np.nan,6.],
               'c':range(2,18,4)})
df2=DataFrame({'a':[5.,4.,np.nan,3.,7.],
               'b':[np.nan,3.,4.,6.,8.]})
print df1
#输出结果如下:
#      a    b   c
# 0  1.0  NaN   2
# 1  NaN  2.0   6
# 2  5.0  NaN  10
# 3  NaN  6.0  14
print df2
#输出结果如下:
#      a    b
# 0  5.0  NaN
# 1  4.0  3.0
# 2  NaN  4.0
# 3  3.0  6.0
# 4  7.0  8.0
print df1.combine_first(df2) #用df2里的数据为df1中的数据为nan的数据打补丁
#输出结果如下:
#      a    b     c
# 0  1.0  NaN   2.0
# 1  4.0  2.0   6.0
# 2  5.0  4.0  10.0
# 3  3.0  6.0  14.0
# 4  7.0  8.0   NaN
  1. 重塑和轴向旋转:

pandas对象中有许多用于重新排列表格型数据的基础运算。这些函数也称作重塑或轴向旋转运算。

(1)stack:将数据的列"旋转"为行。(将DataFrame转换成Series,而Series无stack方法)

(2)unstack:与stack相反的操作,将数据的行“旋转”为列。(将Series转换成DataFrame,DataFrame还是DataFrame)

重塑层次化索引:

层次化索引为DataFrame数据的重排任务提供了一个具有良好一致性的方式。主要功能有以下二个方法:

层次化索引为DataFrame数据的
stack:将数据的列"旋转"为行,将DataFrame转换成Series,Series无stack()方法
unstack:将数据的行"旋转"为列,将Series转换成DataFrame了,DataFrame还是DataFrame

(1)将DataFrame的列旋转为行:DataFrame.stack()
data=DataFrame(np.arange(6).reshape((2,3)),
               index=pd.Index(['Ohio','Colorado'],name='state'),
               columns=pd.Index(['one','two','three'],name='number'))
print data
#输出结果如下:
# number    one  two  three
# state
# Ohio        0    1      2
# Colorado    3    4      5
result=data.stack()
print result
# #输出结果如下:
# # state     number
# # Ohio      one       0
# #           two       1
# #           three     2
# # Colorado  one       3
# #           two       4
# #           three     5

 (2)对于一个层次化索引的Series,可以用unstack将其重排为一个DataFrame.
print result.unstack()
#输出结果如下:
# number    one  two  three
# state
# Ohio        0    1      2
# Colorado    3    4      5
默认情况下,unstack操作的是最内层(stack也是如此)。传入分层级别的编号或名称即可对其他级别进行unstack操作
print result.unstack(0)
#输出结果如下:
# state   Ohio  Colorado
# number
# one        0         3
# two        1         4
# three      2         5
print result.unstack('state')
#输出结果如下:
# state   Ohio  Colorado
# number
# one        0         3
# two        1         4
# three      2         5

(3)如果不是所有级别值都能在各分组中找到的话,则unstack操作可能会引入缺失数据:
s1=Series([0,1,2,3],index=['a','b','c','d'])
s2=Series([4,5,6],index=['c','d','e'])
data2=pd.concat([s1,s2],keys=['one','two'])
print data2
#输出结果如下:
# one  a    0
#      b    1
#      c    2
#      d    3
# two  c    4
#      d    5
#      e    6
# dtype: int64
print data2.unstack()
#输出结果如下:
#        a    b    c    d    e
# one  0.0  1.0  2.0  3.0  NaN
# two  NaN  NaN  4.0  5.0  6.0

(4)stack默认会滤除缺失数据,因此该运算是可逆的:
# print data2.stack() #报错'Series' object has no attribute 'stack'
#可以对data2.unstack()后的DataFrame进行stack()
print data2.unstack().stack(dropna=False) #DataFrame转换成Series了,且列变成行了
#输出结果如下:
# 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
print data2.unstack().unstack() #data2.unstack()的行变成列
#输出结果如下:
# a  one    0.0
#    two    NaN
# b  one    1.0
#    two    NaN
# c  one    2.0
#    two    4.0
# d  one    3.0
#    two    5.0
# e  one    NaN
#    two    6.0

(5)对DataFrame进行unstack操作时,作为旋转轴的级别将会成为结果中的最低级别
df=DataFrame({'left':result,'right':result+5},
             columns=pd.Index(['left','right'],name='side'))
print df
#result的内容如下:
# # state     number
# # Ohio      one       0
# #           two       1
# #           three     2
# # Colorado  one       3
# #           two       4
# #           three     5
#df的结果如下:
# side             left  right
# state    number
# Ohio     one        0      5
#          two        1      6
#          three      2      7
# Colorado one        3      8
#          two        4      9
#          three      5     10
print df.unstack('state') #将state的行旋转为列
#输出结果如下:
# side   left          right
# state  Ohio Colorado  Ohio Colorado
# number
# one       0        3     5        8
# two       1        4     6        9
# three     2        5     7       10
print df.unstack('state').stack('side') #将上面的再stack将列为side的旋转为行(即left,right)
#输出结果如下:
# state         Colorado  Ohio
# number side
# one    left          3     0
#        right         8     5
# two    left          4     1
#        right         9     6
# three  left          5     2
#        right        10     7

将"长格式"转换为"宽格式":

时间序列数据通常是以所谓的"长格式"(long)或"堆叠格式"(stacked)存储在数据库和CSV中的。

关系型数据库通常是主键形式提供了关系的完整性,而且提供了更为简单的查询支持。但对于长格式的数据操作起来就不那么轻松了。

而DataFrame可以把主键中不同的Item值分别形成一列,date列中的时间值则用作索引,可以用DataFrame的pivot方法完全可以实现这个转换。

import pandas as pd
import numpy as np
from pandas import Series,DataFrame

ldata=DataFrame({'date':['1959-03-31 00:00:00','1959-03-31 00:00:00','1959-03-31 00:00:00',
                         '1959-06-30 00:00:00','1959-06-30 00:00:00','1959-06-30 00:00:00',
                         '1959-09-30 00:00:00','1959-09-30 00:00:00','1959-09-30 00:00:00','1959-12-31 00:00:00'],
                 'item':['realgdp','infl','unemp','realgdp','infl','unemp','realgdp','infl','unemp','realgdp'],
                 'value':['2710.349','0.000','5.800','2778.801','2.340','5.100','2775.488','2.740','5.300','2785.204']

})
print ldata
#输出结果如下:
#                   date     item     value
# 0  1959-03-31 00:00:00  realgdp  2710.349
# 1  1959-03-31 00:00:00     infl     0.000
# 2  1959-03-31 00:00:00    unemp     5.800
# 3  1959-06-30 00:00:00  realgdp  2778.801
# 4  1959-06-30 00:00:00     infl     2.340
# 5  1959-06-30 00:00:00    unemp     5.100
# 6  1959-09-30 00:00:00  realgdp  2775.488
# 7  1959-09-30 00:00:00     infl     2.740
# 8  1959-09-30 00:00:00    unemp     5.300
# 9  1959-12-31 00:00:00  realgdp  2785.204

(1)使用DataFrame的pivot的方法
pivoted=ldata.pivot('date','item','value')
print pivoted.head()
#输出结果如下:
# item                  infl   realgdp  unemp
# date
# 1959-03-31 00:00:00  0.000  2710.349  5.800
# 1959-06-30 00:00:00  2.340  2778.801  5.100
# 1959-09-30 00:00:00  2.740  2775.488  5.300
# 1959-12-31 00:00:00   None  2785.204   None

(2)前两个参数值分别用作行和列索引的列名,最后一个参数值则是用于填充DataFrame的数据列的列名。
#假设有两个需要参与重塑的数据列:
ldata['value2']=np.random.randn(len(ldata))
print ldata[:10]
#输出结果如下:
#                   date     item     value    value2
# 0  1959-03-31 00:00:00  realgdp  2710.349  0.935557
# 1  1959-03-31 00:00:00     infl     0.000  1.609324
# 2  1959-03-31 00:00:00    unemp     5.800 -0.753734
# 3  1959-06-30 00:00:00  realgdp  2778.801 -0.668879
# 4  1959-06-30 00:00:00     infl     2.340 -0.256601
# 5  1959-06-30 00:00:00    unemp     5.100  0.537770
# 6  1959-09-30 00:00:00  realgdp  2775.488  1.073817
# 7  1959-09-30 00:00:00     infl     2.740 -0.027340
# 8  1959-09-30 00:00:00    unemp     5.300 -0.531161
# 9  1959-12-31 00:00:00  realgdp  2785.204  0.706080

(3)如果忽略掉最后一个参数,得到的DataFrame就会带有层次化的列
pivoted=ldata.pivot('date','item')
print pivoted[:5]
#输出结果如下:
#                      value                     value2
# item                  infl   realgdp  unemp      infl   realgdp     unemp
# date
# 1959-03-31 00:00:00  0.000  2710.349  5.800 -0.505690 -1.090732 -2.123859
# 1959-06-30 00:00:00  2.340  2778.801  5.100 -0.940028 -2.204997 -1.195357
# 1959-09-30 00:00:00  2.740  2775.488  5.300 -0.636424  0.510898  1.105585
# 1959-12-31 00:00:00   None  2785.204   None       NaN -0.203154       NaN

(4)注意,pivot其实只是一个快捷方式而己:用set_index创建层次化索引,再用unstack重塑。
unstacked=ldata.set_index(['date','item']).unstack('item')
print unstacked[:7]
#输出结果如下:
#                      value                     value2
# item                  infl   realgdp  unemp      infl   realgdp     unemp
# date
# 1959-03-31 00:00:00  0.000  2710.349  5.800 -0.380805 -2.499867 -1.398593
# 1959-06-30 00:00:00  2.340  2778.801  5.100 -0.168914  0.435372 -1.454938
# 1959-09-30 00:00:00  2.740  2775.488  5.300 -0.297850 -1.693196  1.615807
# 1959-12-31 00:00:00   None  2785.204   None       NaN  1.551105       NaN

import pandas as pd
import numpy as np
from pandas import Series,DataFrame

df = pd.DataFrame({'foo': ['one', 'one', 'one', 'two', 'two',
                           'two'],
                   'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
                   'baz': [1, 2, 3, 4, 5, 6],
                   'zoo': ['x', 'y', 'z', 'q', 'w', 't']})
print df
#输出结果如下:
#   bar  baz  foo zoo
# 0   A    1  one   x
# 1   B    2  one   y
# 2   C    3  one   z
# 3   A    4  two   q
# 4   B    5  two   w
# 5   C    6  two   t
print df.pivot(index='foo',columns='bar')['baz'] #行索引foo,列bar,值baz
#输出结果如下:
# bar  A  B  C
# foo
# one  1  2  3
# two  4  5  6
print df.pivot(index='foo',columns='bar',values='baz') #与上面的一致
# print df.pivot(index='foo',columns='bar',values=['baz', 'zoo'])
#若是两行的索引一样的话会报错,因为值就不知道对应哪个了
#如下例中bar中的两个索一样
df=pd.DataFrame({"foo":['one','one','two','two'],
                 "bar":['A','A','B','C'],
                 "baz":[1,2,3,4]})
print df
print df.pivot(index='foo',columns='bar',values='baz') #报错,foo,bar为[one,A]不知道对应哪个值了,两个一样的索引
  1. 数据转换:

前面讲的都是数据重排,另一类重要操作则是过滤、清理以及其它的转换工作。

(1)drop_duplicates:删除重复数据

(2)map:函数或映射进行数据转换(map,lambda),map用于修改对象的子集

(3)fillna: 用于填充缺失数据,看做值替换的一种特殊情况。或者用pandas的replace方法替换缺失值(与python的str.replace方法一样)

(4)rename:复制DataFrame并对其行索引和列标签进行修改。若要就地修改某个数据集,传入inplace=True即可

(5)cut:将数据划分阶段(即元面)例不同的年龄阶段,它返回的Categorical对象。而qcut是根据样本分位数对数据进行划分(可以等分)

(6)abs:过滤绝对值,np.abs(data)>3取绝对值>3的数。

(7)np.sign:过滤的区间为-1到1的数组,表示原始值的符号。

(8)take:选取子集,从DataFrame或Series中选取部分子集

(9)get_dummies:DataFrame的某一列中有多个不同的值,可将该列的值作为列名,其值全为1和0.例:第一行只有a的值,则a为1,其它为0

                        Series只有panda.str.get_dummies.

猜你喜欢

转载自blog.51cto.com/13861813/2139742