您的位置:首页 > 编程语言 > Python开发

利用python进行数据分析之数据规整化

2016-02-25 10:01 881 查看
数据分析和建模大部分时间都用在数据准备上,数据的准备过程包括:加载,清理,转换与重塑。

合并数据集

pandas对象中的数据可以通过一些内置方法来进行合并:

pandas.merge可根据一个或多个键将不同DataFrame中的行连接起来,实现类似于数据库中的连接操作。

pandas.cancat表示沿着一条轴将多个对象堆叠到一起。

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

下面将进行分别讲解:

1、数据库风格的DateFrame合并

数据集的合并运算是通过一个或者多个键将行连接起来,主要使用的merge或者join方法。

>>> import pandas as pd
>>> from pandas import DataFrame
>>> import numpy as np
>>> df1=DataFrame({'key':['b','b','a','c','a','a','b'],'data1':range(7)})
>>> df2=DataFrame({'key':['a','b','d'],'data2':range(3)})
>>> 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
#未显示指定用何列拼接,默认用重叠列的作为键,最好显示指定
>>> pd.merge(df1,df2,on='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


#当两个对象列明不同可以进行分别指定
>>> df3=DataFrame({'lkey':['b','b','a','c','a','a','b'],'data1':range(7)})
>>> df4=DataFrame({'rkey':['a','b','d'],'data2':range(3)})
>>> 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
#默认情况下merge函数进行的是交集操作,可以指定how参数来实现左右连接与并集(outer)


#根据多个键进行合并,传入一个由列名组成的列表即可
>>> left=DataFrame({'key1':['foo','foo','bar'],'key2':['one','two','three'],'lval':[1,2,3]})
>>> right=DataFrame({'key1':['foo','foo','bar','bar'],'key2':['one','two','one','two'],'rval':[4,5,6,7]})
>>> pd.merge(left,right,on=['key1','key2'],how='outer')
key1   key2  lval  rval
0  foo    one     1     4
1  foo    two     2     5
2  bar  three     3   NaN
3  bar    one   NaN     6
4  bar    two   NaN     7


对于合并运算需要考虑的最后一个问题是对重复列名的处理,merge有一个suffixes选项,用于指定附加到左右两个DataFrame对象的重叠列名上的字符串:

>>> pd.merge(left,right,on='key1')
key1 key2_x  lval key2_y  rval
0  foo    one     1    one     4
1  foo    one     1    two     5
2  foo    two     2    one     4
3  foo    two     2    two     5
4  bar  three     3    one     6
5  bar  three     3    two     7
>>> 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        two     5
2  foo       two     2        one     4
3  foo       two     2        two     5
4  bar     three     3        one     6
5  bar     three     3        two     7


merge函数的参数表
left参与合并的左侧DataFrame
right参与合并的右侧DataFrame
how选定参与合并的方式(inner,outer,left等)
on用于连接的列名
left_on左侧DataFrame中用于连接的键
right_on右侧DataFrame中用于连接的键
sort根据连接键对合并后的数据进行排序,默认为True
suffixes字符串元组,用于追加到重叠列名的末尾

2、索引上的合并

有时,DataFrame中的连接位于其索引中,在此种情况下可以传入left_index=True或者right_index=True以说明索引应该被用作连接键:

>>> left1=DataFrame({'key':['a','b','a','a','b','c'],'value':range(6)})
>>> right1=DataFrame({'group':[3.5,7]},index=['a','b'])
>>> left1
key  value
0   a      0
1   b      1
2   a      2
3   a      3
4   b      4
5   c      5
>>> right1
group
a    3.5
b    7.0


对于层次化索引数据,相对更为复杂些,在这种情况下,必须以列表的形式指明用作合并键的多个列

>>> lenth=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=[['neveda','neveda','ohio','ohio','ohio','ohio'],[2001,2000,2000,2000,2001,2002]],columns=['event1','event2'])
>>> lenth
data    key1  key2
0     0    ohio  2000
1     1    ohio  2001
2     2    ohio  2002
3     3  nevada  2001
4     4  nevada  2002
>>> righth
event1  event2
neveda 2001       0       1
2000       2       3
ohio   2000       4       5
2000       6       7
2001       8       9
2002      10      11
>>> pd.merge(lenth,righth,left_on=['key1','key2'],right_index=True)
data  key1  key2  event1  event2
0     0  ohio  2000       4       5
0     0  ohio  2000       6       7
1     1  ohio  2001       8       9
2     2  ohio  2002      10      11


DataFrame还有一个join实例方法,它可以更为方便的实现按索引合并,还可以合并多个带有相同或者相似索引的DataFrame对象,而不管其是否有重叠的列:

>>> left2=DataFrame([[1,2],[3,4],[5,6]],index=['a','c','e'],columns=['ohio','nevada'])
>>> left2
ohio  nevada
a     1       2
c     3       4
e     5       6
>>> right2=DataFrame([[7,8],[9,10],[11,12],[13,14]],index=['b','c','d','e'],columns=['missouri','alambda'])
>>> right2
missouri  alambda
b         7        8
c         9       10
d        11       12
e        13       14
>>> left2.join(right2,how='outer')
ohio  nevada  missouri  alambda
a     1       2       NaN      NaN
b   NaN     NaN         7        8
c     3       4         9       10
d   NaN     NaN        11       12
e     5       6        13       14


3、轴向连接

纵向上,numpy有一个用于合并原始numpy数组的concatenation函数:

>>> arr=np.arange(12).reshape((3,4))
>>> arr
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])
>>> np.concatenate([arr,arr],axis=1)
array([[ 0,  1,  2,  3,  0,  1,  2,  3],
[ 4,  5,  6,  7,  4,  5,  6,  7],
[ 8,  9, 10, 11,  8,  9, 10, 11]])
>>> np.concatenate([arr,arr],axis=0)
array([[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11],
[ 0,  1,  2,  3],
[ 4,  5,  6,  7],
[ 8,  9, 10, 11]])


#pandas的concat函数提供了一种能够解决这些问题的可靠方式,默认情况下,concat在0轴上工作,
>>> s1=pd.Series([0,1],index=['a','b'])
>>> s2=pd.Series([2,3,4],index=['c','d','e'])
>>> s3=pd.Series([5,6],index=['f','g'])
>>> pd.concat([s1,s2,s3])
a    0
b    1
c    2
d    3
e    4
f    5
g    6
dtype: int64
#axis=1时,得到一个DataFrame对象
>>> pd.concat([s1,s2,s3],axis=1)
0   1   2
a   0 NaN NaN
b   1 NaN NaN
c NaN   2 NaN
d NaN   3 NaN
e NaN   4 NaN
f NaN NaN   5
g NaN NaN   6


可以通过join_axes指定要在其他轴上使用的索引:

>>> s4=pd.concat([s1*5,s3])
>>> s4
a    0
b    5
f    5
g    6
dtype: int64
>>> pd.concat([s1,s4],axis=1,join_axes=[['a','c','b','e']])
0   1
a   0   0
c NaN NaN
b   1   5
e NaN NaN


 当你需要区分参与连接的片段时,可以在连接轴上创建一个层次化索引,使用key参数可以达到这个目的

>>> result=pd.concat([s1,s2,s3],keys=['one','two','three'])
>>> result
one    a    0
b    1
two    c    2
d    3
e    4
three  f    5
g    6
dtype: int64


#如果沿着axis=1对Series进行合并,则keys会变成合并后DataFrame的列头
>>> pd.concat([s1,s2,s3],keys=['one','two','three'],axis=1)
one  two  three
a    0  NaN    NaN
b    1  NaN    NaN
c  NaN    2    NaN
d  NaN    3    NaN
e  NaN    4    NaN
f  NaN  NaN      5
g  NaN  NaN      6


最后一个需要考虑的问题是,跟当前分析无关的DataFrame索引,直接传入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'])
>>> df1
a         b         c         d
0 -1.928978 -1.202455 -0.180614  0.693538
1 -1.234482  0.664544  0.259534  0.429279
2  0.305255  0.133844  0.934637  0.243345
>>> df2
b         d         a
0 -1.582425  0.055378  0.288906
1 -0.381170  0.731310 -0.661805
>>> pd.concat([df1,df2],ignore_index=True)
a         b         c         d
0 -1.928978 -1.202455 -0.180614  0.693538
1 -1.234482  0.664544  0.259534  0.429279
2  0.305255  0.133844  0.934637  0.243345
3  0.288906 -1.582425       NaN  0.055378
4 -0.661805 -0.381170       NaN  0.731310
#注意区分与下面区别
>>> pd.concat([df1,df2])
a         b         c         d
0 -1.928978 -1.202455 -0.180614  0.693538
1 -1.234482  0.664544  0.259534  0.429279
2  0.305255  0.133844  0.934637  0.243345
0  0.288906 -1.582425       NaN  0.055378
1 -0.661805 -0.381170       NaN  0.731310


4、合并重叠数据

还有一种数据不能用简单的合并或者连接运算来处理比如你有可能索引全部或部分重叠的两个数据集:

>>> 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'])
>>> a
f    NaN
e    2.5
d    NaN
c    3.5
b    4.5
a    NaN
dtype: float64
>>> b
f    0
e    1
d    2
c    3
b    4
a    5
dtype: float64
>>> np.where(pd.isnull(a),b,a)
array([ 0. ,  2.5,  2. ,  3.5,  4.5,  5. ])
#可以看作用参数对象中的数据为调用者对象的缺失数据打补丁


也可用combine_first方法

>>> df1=DataFrame({'a':[1,np.nan,5,np.nan],'b':[np.nan,2,np.nan,6],'c':range(2,18,4)})
>>> df1
a   b   c
0   1 NaN   2
1 NaN   2   6
2   5 NaN  10
3 NaN   6  14
>>> df2=DataFrame({'a':[5,4,np.nan,3,7],'b':[np.nan,3,4,6,8]})
>>> df2
a   b
0   5 NaN
1   4   3
2 NaN   4
3   3   6
4   7   8
>>> df1.combine_first(df2)
a   b   c
0  1 NaN   2
1  4   2   6
2  5   4  10
3  3   6  14
4  7   8 NaN


重塑和轴向旋转

1、重塑层次化索引

层次化索引技术为DataFrame数据重拍运算提供了一种具有良好一致性的方式,主要功能有二:

stack,将数据的列旋转为行

unstack,将数据的行旋转为列

>>> data=DataFrame(np.arange(6).reshape((2,3)),index=['ohio','colorado'],columns=['one','two','three'])
>>> data
one  two  three
ohio        0    1      2
colorado    3    4      5
>>> data.index
Index([u'ohio', u'colorado'], dtype='object')
>>> data.index.name='state'
>>> data.columns.name='number'
>>> data
number    one  two  three
state
ohio        0    1      2
colorado    3    4      5
>>> data.stack()
state     number
ohio      one       0
two       1
three     2
colorado  one       3
two       4
three     5
dtype: int32
#将列转化为行,得到一个Series
#对于一个层次化索引的Series,可以用unstack将其重排为一个DataFrame


默认情况下unstack操作的是最内层的,可传入分层级别的编号和名称参数,即可对其他级别进行untack操作:

>>> result=data.stack()
>>> result
state     number
ohio      one       0
two       1
three     2
colorado  one       3
two       4
three     5
dtype: int32
>>> result.unstack(0)
state   ohio  colorado
number
one        0         3
two        1         4
three      2         5
>>> result.unstack('state')
state   ohio  colorado
number
one        0         3
two        1         4
three      2         5


在对DataFrame,进行unset操作时,作为旋转轴的级别将会成为结果中的最低级别(即旋转轴索引将成为最内层索引):

>>> df=DataFrame({'left':result,'right':result+5},columns=['left','right'])
>>> df.columns.name='side'
>>> 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
>>> df.unstack('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
>>> df.unstack('state').stack('side')
state         ohio  colorado
number side
one    left      0         3
right     5         8
two    left      1         4
right     6         9
three  left      2         5
right     7        10


数据转换

除了数据合并与重排之外,另一类重要的操作是过滤,清理。

1、移除重复数据

DataFrame的duplicated方法返回一个布尔型Series,表示各行是否为重复行

>>> data=DataFrame({'k1':['one']*3+['two']*4,'k2':[1,1,2,3,3,4,4]})
>>> data
k1  k2
0  one   1
1  one   1
2  one   2
3  two   3
4  two   3
5  two   4
6  two   4
>>> data.duplicated()
0    False
1     True
2    False
3    False
4     True
5    False
6     True
dtype: bool
#drop_duplicates方法用于返回一个移除了重复行的DataFrame,删除那些为True的行
>>> data.drop_duplicates()
k1  k2
0  one   1
2  one   2
3  two   3
5  two   4
#可以指定过滤重复列的项
>>> data.drop_duplicates(['k1'])
k1  k2
0  one   1
3  two   3

#以上两个方法默认保留第一个出现的组合值,传入take_last=True则可以保留最后一个


2、利用函数或映射进行数据转换

Series的map方法可以接受一个函数或含有映射关系的字典型对象

>>> data=DataFrame({'food':['bacon','pulled prok','bacon','pastrami','corned beef','bacon','pastrami','honey ham','nova lox'],'ounce':[4,3,12,6,7.5,8,3,5,6]})
>>> data
food  ounce
0        bacon    4.0
1  pulled prok    3.0
2        bacon   12.0
3     pastrami    6.0
4  corned beef    7.5
5        bacon    8.0
6     pastrami    3.0
7    honey ham    5.0
8     nova lox    6.0
>>> meat_to_animal={'bacon':'pig','pulled pork':'pig','pastrami':'cow','honey ham':'pig','nova lox':'salmon'}
>>> data['animal']=data['food'].map(meat_to_animal)
>>> data
food  ounce  animal
0        bacon    4.0     pig
1  pulled prok    3.0     NaN
2        bacon   12.0     pig
3     pastrami    6.0     cow
4  corned beef    7.5     NaN
5        bacon    8.0     pig
6     pastrami    3.0     cow
7    honey ham    5.0     pig
8     nova lox    6.0  salmon


3、替换值

利用fillna方法填充缺失数据可以看作值替换的一种特殊情况,但是使用replace则提供了一种实现该功能更简单的方法:

>>> pd.Series([1,-999,2,-999,-1000,3])
0       1
1    -999
2       2
3    -999
4   -1000
5       3
dtype: int64
>>> data=pd.Series([1,-999,2,-999,-1000,3])
>>> data.replace(-999,np.nan)
0       1
1     NaN
2       2
3     NaN
4   -1000
5       3
dtype: float64
#如果想一次性替换多个值,可以传入一个由待替换值组成的列表以及一个替换值:

>>> data.replace([-999,-1000],np.nan)
0 1
1 NaN
2 2
3 NaN
4 NaN
5 3
dtype: float64

#如果希望对不同的值做不同的替换,则传入一个由替换关系组成的列表即可:

>>> data.replace([-999,-1000],[np.nan,0])
0 1
1 NaN
2 2
3 NaN
4 0
5 3
dtype: float64

#传入的参数也可以是字典形式:{-999:np.nan,-1000:0}

4、重命名轴索引

轴标签也可以通过函数或映射进行转换,从而得到一个新对象。轴也可以被修改,而无需创建一个新的数据结构。

轴标签也可以使用map方法

>>> df1=DataFrame(np.arange(12).reshape((3,4)),index=['ohio','colorado','new york'],columns=['one','two','three','four'])
>>> df1
one  two  three  four
ohio        0    1      2     3
colorado    4    5      6     7
new york    8    9     10    11
>>> df1.index.map(str.upper)
array(['OHIO', 'COLORADO', 'NEW YORK'], dtype=object)
>>> df1.index=df1.index.map(str.upper)
>>> df1
one  two  three  four
OHIO        0    1      2     3
COLORADO    4    5      6     7
NEW YORK    8    9     10    11
#如果不想修改原始数据可以创建数据的转换版
>>> df1.rename(columns=str.upper)
ONE  TWO  THREE  FOUR
OHIO        0    1      2     3
COLORADO    4    5      6     7
NEW YORK    8    9     10    11
#rename也可以结合字典型对象实现对部分轴标签进行更新
>>> df1.rename(index={'OHIO':'INDIANA'},columns={'three':'peekaboo'})
one  two  peekaboo  four
INDIANA     0    1         2     3
COLORADO    4    5         6     7
NEW YORK    8    9        10    11


5、离散化和面元划分

为了便于分析,连续数据常常需要被离散化或拆分为"面元",此时需要使用pandas库中的cut函数:

>>> ages=[20,22,25,27,21,23,37,31,61,45,41,32]
>>> bins=[18,25,35,60,100]
>>> cats=pd.cut(ages.bins)
>>> cats=pd.cut(ages,bins)
>>> cats
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
Length: 12
Categories (4, object): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
#pandas返回的是一个特殊的categorcal对象,它含有一个表示不同分类名称的levels数组以及一个为年龄数据进行标号的labels属性
>>> cats.labels
array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)
>>> cats.levels
Index([u'(18, 25]', u'(25, 35]', u'(35, 60]', u'(60, 100]'], dtype='object')


也可以设置自定义的面元名称,将labels选项设置为一个列表或元组即可:

>>> pd.cut(ages,bins,labels=['youth','youngadult','middleaged','senior'])
[youth, youth, youth, youngadult, youth, ..., youngadult, senior, middleaged, middleaged, youngadult]
Length: 12
Categories (4, object): [youth < youngadult < middleaged < senior]


如果cut传入的是面元的数量而不是确切的面元边界,则它会根据数据的最小值和最大值计算等长的面元,实现均分:

>>> data=np.random.randn(20)
>>> pd.cut(data,4,precision=2)
[(-1.018, 0.095], (-1.018, 0.095], (0.095, 1.21], (0.095, 1.21], (-1.018, 0.095], ..., (0.095, 1.21], (0.095, 1.21], (-1.018, 0.095], (0.095, 1.21], (-1.018, 0.095]]
Length: 20
Categories (4, object): [(-2.14, -1.018] < (-1.018, 0.095] < (0.095, 1.21] < (1.21, 2.32]]


qcut是一个类似与cut的函数,它可以根据样本分位数对数据进行面元划分:

>>> data=np.random.randn(1000)
>>> cats=pd.qcut(data,4)    #按四分位数进行切割
>>> cats
[(0.644, 3.0404], (-0.00691, 0.644], (0.644, 3.0404], (-0.00691, 0.644], (0.644, 3.0404], ..., (-0.00691, 0.644], (-0.00691, 0.644], (0.644, 3.0404], [-3.753, -0.709], (-0.709, -0.00691]]
Length: 1000
Categories (4, object): [[-3.753, -0.709] < (-0.709, -0.00691] < (-0.00691, 0.644] < (0.644, 3.0404]]
>>> pd.value_counts(cats)
(0.644, 3.0404]       250
(-0.00691, 0.644]     250
(-0.709, -0.00691]    250
[-3.753, -0.709]      250
dtype: int64


6、检测和过滤异常值

异常值的过滤或变换运算在很大程度上就是数组运算:

>>> data=DataFrame(np.random.randn(1000,4))
>>> data.describe()
0            1            2            3
count  1000.000000  1000.000000  1000.000000  1000.000000
mean     -0.067684     0.067924     0.025598    -0.002298
std       0.998035     0.992106     1.006835     0.996794
min      -3.428254    -3.548824    -3.184377    -3.745356
25%      -0.774890    -0.591841    -0.641675    -0.644144
50%      -0.116401     0.101143     0.002073    -0.013611
75%       0.616366     0.780282     0.680391     0.654328
max       3.366626     2.653656     3.260383     3.927528
>>> col=data[3]    #选取具体某列
>>> col[np.abs(col)>3]
97     3.927528
305   -3.399312
400   -3.745356
Name: 3, dtype: float64
#找出绝对值大小超过3的值


7、排列和随机抽样

利用numpy.random.permutation函数可以实现对Series或DataFrame的列的排列工作:

>>> df=DataFrame(np.arange(5*4).reshape(5,4))
>>> sapmler=np.random.permutation(5)
>>> df
0   1   2   3
0   0   1   2   3
1   4   5   6   7
2   8   9  10  11
3  12  13  14  15
4  16  17  18  19
>>> df.take(sapmler)
0   1   2   3
1   4   5   6   7
0   0   1   2   3
2   8   9  10  11
3  12  13  14  15
4  16  17  18  19


8、计算指标/哑变量

另一种常见的统计建模或机器学习的转换方式是将分类变量转换为哑变量矩阵,pandas有一个get_dummies函数可以实现该功能

>>> df=DataFrame({'key':['b','b','a','c','a','b'],'data1':range(6)})
>>> df
data1 key
0      0   b
1      1   b
2      2   a
3      3   c
4      4   a
5      5   b
>>> pd.get_dummies(df['key'])
a  b  c
0  0  1  0
1  0  1  0
2  1  0  0
3  0  0  1
4  1  0  0
5  0  1  0


有时候需要给DataFrame的列加上一个前缀,能够与其他的数据进行合并,get_dummies函数的prefix参数可以实现该功能

>>> dum=pd.get_dummies(df['key'],prefix='key')
>>> df_with_dummy=df[['data1']].join(dum)
>>> df_with_dummy
data1  key_a  key_b  key_c
0      0      0      1      0
1      1      0      1      0
2      2      1      0      0
3      3      0      0      1
4      4      1      0      0
5      5      0      1      0


结合cut与get_dummies离散化二元化数据:

>>> values=np.random.randn(10)
>>> values
array([ 0.04648638, -0.61044135, -0.39498189,  1.19991518, -0.45181441,
-0.15538512, -0.15351407,  0.01119376, -0.05055467,  0.42021107])
>>> bins=[0,0.2,0.4,0.6,0.8,1]
>>> pd.get_dummies(pd.cut(values,bins))
(0, 0.2]  (0.2, 0.4]  (0.4, 0.6]  (0.6, 0.8]  (0.8, 1]
0         1           0           0           0         0
1         0           0           0           0         0
2         0           0           0           0         0
3         0           0           0           0         0
4         0           0           0           0         0
5         0           0           0           0         0
6         0           0           0           0         0
7         1           0           0           0         0
8         0           0           0           0         0
9         0           0           1           0         0


字符串操作

python能够成为流行的数据处理语言,部分原因是其简单易用的字符串和文本处理功能。

1、字符串对象方法

以逗号分隔的字符串可以用split拆分为数段,split常常结合strip一起使用:

>>> val='a,b, guido'
>>> val.split(',')
['a', 'b', ' guido']
>>> pieces=[x.strip() for x in val.split(',')]
>>> pieces
['a', 'b', 'guido']


利用加法可以将子字符串以双冒号的形式连接起来,但是更简便的方式是使用字符串'::'的join方法传入一个元组或列表:

>>> first,second,third=pieces
>>> '::'.join(pieces)
'a::b::guido'


另一类方法关注的是子串定位,检测子串的最佳方式是利用python的in关键字(index与find同样适用):

>>> 'guido'in val
True
>>> val.index(',')
1
>>> val.find(':')
-1
>>>
#如果找不到字符串,find返回一个-1,index会引发异常


此外,还有一个count函数,可返回指定子串的出现次数,replace用于将指定模式替换为另一个模式:

>>> val.count(',')
2
>>> val.replace(',',':')
'a:b: guido'


python内置字符串说明列表
count返回子串在字符串中出现的次数
endswith,startswith如果字符串以某个后缀结尾(开头),返回ture
join将字符串用作连接其他字符串序列的分隔符
index如果在字符串中找到子串,返回子串在字符串中的第一个字符所在的位置
find如果在字符串中找到子串,返回子串在字符串中的第一个字符所在的位置,没找到则返回-1
replace用一个字符串替换指定字符串
strip,rstrip,lstrip去除空白符,包括换行符
split通过指定的分隔符将字符串拆分为一组字符串
lower,upper将字符串转换为小写或大写
2、正则表达式

正则表达式提供了一种灵活在文本中搜索或匹配字符串模式的方式。

re模块的函数可以分为三个大类:模式匹配,替换和拆分,这三个是相辅相成:

>>> text="foo  bar\t baz  \tqux"
>>> text
'foo  bar\t baz  \tqux'
>>> re.split('\s+',text)
['foo', 'bar', 'baz', 'qux']


一般可以用re.compile编译一个可重用的regrex对象,且针对许多字符串用同一正则表达式时,通过使用re.compile可以节省大量cpu计算时间:

>>> regrex=re.compile('\s+')
>>> regrex.split(text)
['foo', 'bar', 'baz', 'qux']
#如果只希望得到regrex匹配的所有模式,可以使用findall方法
>>> regrex.findall(text)
['  ', '\t ', '  \t']


match功能和search功能跟findall功能类似,findall返回的是字符串中所有的匹配项,而search只返回第一个匹配项,match更加严格,它只匹配字符串的首部,sub方法会将匹配到的模式替换为指定字符串,并返回得到的字符串。

ps:想要用好正则表达式,需要大量的额外练习与使用

3、pandas中矢量化的字符串函数

清理待分析的散乱数据时,常常需要做一些字符串规整化的工作:

通过data.map,所有字符串和正则表达式方法都能被用于各个值,但传入na就会报错,Series提供了一些能够跳过NA值的字符串操作方法

>>> data={'Dave':'dave@google.com','Steve':'steve@gmail.com','Rob':'rob@gmail.com','Wes':np.nan}
>>> data=pd.Series(data)
>>> data
Dave     dave@google.com
Rob        rob@gmail.com
Steve    steve@gmail.com
Wes                  NaN
dtype: object
>>> data.isnull()
Dave     False
Rob      False
Steve    False
Wes       True
dtype: bool
>>> data.str.contains('gmail')
Dave     False
Rob       True
Steve     True
Wes        NaN
dtype: object


这里也可以通过正则表达式解决:

>>> data.str.findall(pattern,flags=re.IGNORECASE)
Dave     [dave@google.com]
Rob        [rob@gmail.com]
Steve    [steve@gmail.com]
Wes                    NaN
dtype: object


有两个方法可以实现矢量化的元素获取操作:1)使用str.get,2)在str属性上使用索引
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: