python之数据的转换及字符串操作

数据的过滤、清理和其他转换工作也是数据规整化的一大类操作。

一、移除重复数据

  • duplicated方法返回的是一个布尔型Series,表示各行是否是重复行,默认判断全部列且默认第一个出现值为True
  • drop_duplicates方法移除重复行,默认判断全部列,默认保留第一个出现的值
data=DataFrame({'k1':['one']*3+['two']*4,'k2':[1,1,2,3,3,4,4]})
#duplicated方法返回的是一个布尔型Series,表示各行是否是重复行,且默认第一个出现值为True
d1=data.duplicated()
#drop_duplicates方法移除重复行,默认保留第一个出现的值
d2=data.drop_duplicates()
#保留最后一个出现的值
d3=data.drop_duplicates(keep='last')
#指定部分列进行重复项判断
d4=data.drop_duplicates(['k1'])
"""
data:                 d1:              d2:                d3:             d4:
    k1  k2                                k1  k2           k1  k2         k1  k2
0  one   1          0    False        0  one   1       1  one   1     0  one   1
1  one   1          1     True        2  one   2       2  one   2     3  two   3
2  one   2          2    False        3  two   3       4  two   3
3  two   3          3    False        5  two   4       6  two   4
4  two   3          4     True
5  two   4          5    False
6  two   4          6     True
"""

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

在对数据集进行转换时,利用map函数可以对数组、Series或DataFrame列中的值来实现元素级转换以及其他数据的清理工作。

#map函数
data=DataFrame({'names':['Bob','Jane','Tom','Ann'],'ages':[22,25,26,20]})
#假设这四个人都是18岁入职的,现计算他们的工作年限years
data['years']=data['ages'].map(lambda x:x-18)
"""
data:                    map映射后:
   ages names         ages names  years
0    22   Bob      0    22   Bob      4
1    25  Jane      1    25  Jane      7
2    26   Tom      2    26   Tom      8
3    20   Ann      3    20   Ann      2
"""

三、替换值

利用fillna方法填充缺失数据可以看做值替换的一种特殊情况。map函数可以用于修改对象的数据子集,而replace则提供了一种实现该功能的更简单、更灵活的方式。

#replace函数
data=Series([1,-999,2,-1000,3,-999])
#第一个参数是to_place(被换的值),第二个参数是value(换后的值)
d1=data.replace(-999,np.nan)
#一次性换多个值,传入一个由待替换组成的列表
d2=data.replace([-999,-1000],np.nan)
#对不同的值进行不同的替换,可以传入列表
d3=data.replace([-999,-1000],[np.nan,0])
#对不同的值进行不同的替换,还可以传入字典
d4=data.replace({-999:np.nan,-1000:0})
"""
data:             d1:                 d2:              d3/d4:
0       1       0       1.0         0    1.0         0    1.0
1    -999       1       NaN         1    NaN         1    NaN
2       2       2       2.0         2    2.0         2    2.0
3   -1000       3   -1000.0         3    NaN         3    0.0
4       3       4       3.0         4    3.0         4    3.0
5    -999       5       NaN         5    NaN         5    NaN
dtype: int64    dtype: float64      dtype: float64    dtype: float64
"""

四、离散化和面元划分

为了便于分析,连续数据常常被离散化或拆成”面元“(bin)。例如,有一组人员数据,而你希望将他们划分为不同的年龄组:你可以使用pandas的cut函数。

#cut函数
ages=[24,19,33,45,56,48,46,55,20,24,23,43,62]
#你想将该数据划分为18-25,26-35,36-60,60以上的几个面元(左不包括,右包括,即(])
bins=[18,25,35,60,100]
#cut函数默认左不包括,右包括,即左开右闭,可以设置right=True,使得左包括
cats=pd.cut(ages,bins)
"""返回的是category 对象
cats=[(18, 25], (18, 25], (25, 35], (35, 60], (35, 60], ..., (18, 25], (18, 25], (18, 25], (35, 60], (60, 100]]
Length: 13
Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]
"""
#为年龄数组进行标号的codes属性
cats.codes   #array([0, 0, 1, ..., 0, 2, 3], dtype=int8)
#显示不同分类名称
cats.categories  #IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]])
#
pd.value_counts(cats)
"""
(35, 60]     6
(18, 25]     5
(60, 100]    1
(25, 35]     1
dtype: int64
"""

五、检测和过滤异常值

异常值(又称孤立值或离群值)的过滤或变换运算在很大程度上其实就是数组运算。

#异常值过滤和检测
data=DataFrame(np.random.randn(1000,4))
data.describe()
"""data.describe():
                 0            1            2            3
count  1000.000000  1000.000000  1000.000000  1000.000000
mean      0.021462     0.028700    -0.048713     0.021413
std       0.967959     1.027700     0.993056     0.991414
min      -2.750967    -3.856974    -2.777925    -3.652881
25%      -0.625540    -0.694761    -0.771328    -0.645742
50%       0.017576     0.007304    -0.048511    -0.010639
75%       0.690868     0.727350     0.616060     0.726299
max       3.065890     3.288369     2.852040     2.706435
"""
#若找出第三列绝对值大于3的值
data[3][np.abs(data[3])>3]   #result:158   -3.652881
#找出含有绝对值大于3的值的所有行,利用DataFrame和any
data[(np.abs(data)>3).any(1)]
"""
            0         1         2         3
38   3.065890 -0.739700 -1.112838 -0.329292
158 -0.412867  0.670742  0.808559 -3.652881
340 -0.056876  3.096786 -1.502054  0.763512
366 -1.018817 -3.856974 -1.069169 -0.055118
434 -2.116043  3.288369 -0.781302 -1.276858
628  0.317649 -3.416358  0.912362  0.525939
648 -0.440840 -3.572644 -0.591399 -1.177463
"""
#将值限制在[-3,3]之间
#np.sign函数返回的是1和-1的数组,代表原始值的符号
data[(np.abs(data)>3)]=np.sign(data)*3
data.describe()
"""
result:
                 0            1            2            3
count  1000.000000  1000.000000  1000.000000  1000.000000
mean      0.021396     0.030161    -0.048713     0.022066
std       0.967754     1.020466     0.993056     0.989204
min      -2.750967    -3.000000    -2.777925    -3.000000
25%      -0.625540    -0.694761    -0.771328    -0.645742
50%       0.017576     0.007304    -0.048511    -0.010639
75%       0.690868     0.727350     0.616060     0.726299
max       3.000000     3.000000     2.852040     2.706435
"""

六、排序和随机采样

利用numpy.random.permutation函数可以提轻松实现对Series或DataFrame的列的排序工作。通过需要排列的轴的长度调用permutation,可产生一个新的顺序的整数数组:

#np.random.permutation(len(df))         #result:array([0, 1, 4, 2, 3])
#np.random.permutation(len(df))[:3]     #result:array([0, 1, 4])
bags=np.array([5,7,-1,6,4])
sampler=np.random.randint(0,len(bags),size=10)
#sampler=array([2, 2, 1, 1, 3, 1, 3, 0, 2, 1])
#bags和sampler之间的关系:bags=[5,7,-1,6,4]的下标是[0,1,2,3,4];samplers中数代表的是bags的下标
draws=bags.take(sampler)
#draws=array([-1, -1,  7,  7,  6,  7,  6,  5, -1,  7])

七、计算指标/哑变量

另一种常用于统计建模或机器学习的转换方式是:将分类变量(categorical variable)转换为”哑变量矩阵“(dummpy matrix)或”指标矩阵“(indicator matrix)。如果DataFrame的某一列中含有k个不同的值,则可以派生出一个k列矩阵或DataFrame(其值全为1和0)。pandas有一个get_dummies函数可以实现该功能。

#计算指标/哑变量
df1=DataFrame({'key':['b','b','a','c','a','b'],'data':range(6)})
#pd.get_dummies(data,prifix=None,...,columns=None)函数还可加前缀和列名等
df2=pd.get_dummies(df['key'])
"""
df1:                  df2:
   data key          a  b  c
0     0   b       0  0  1  0
1     1   b       1  0  1  0
2     2   a       2  1  0  0
3     3   c       3  0  0  1
4     4   a       4  1  0  0
5     5   b       5  0  1  0
"""

八、字符串操作

python能够成为流行的数据处理语言,部分原因是因其简单易用的字符串和文本处理功能。大部分文本运算都直接做成了字符串对象的内置方法。对于更为复杂的模式匹配和文本操作,则可能要用到正则表达式。pandas对此进行了加强,它使得你能够对整组数据应用字符串表达式和正则表达式,而且能处理烦人的缺失数据。

8.1字符串对象方法

python之数据的转换及字符串操作_第1张图片

python之数据的转换及字符串操作_第2张图片

相关代码:

#字符串操作:
val='a,b, guido'
#split方法通过分隔符拆分字符串
#val分隔符是‘,’,还可以是空格或其他
val.split(',')    #result:['a', 'b', ' guido']
#strip方法:用于修剪空白符(包括换行符)
piece=[x.strip() for x in val.split(',')]   #piece= ['a', 'b', 'guido']
#以分隔符(自定义字符串皆可)形式将子字符串连接起来
'+'.join(piece)    #result:'a+b+guido'
#子字符串定位
'a' in val       #return:True
val.index('g')    #return:5
val.index(':')    #找不到会报错
val.find('g')      #return:5
val.find(':')     #找不到,返回-1
#计算字符子串出现次数
val.count(',')    #return:2
#子字符串的替换,当替换对象为空字符串时,其作用为删除
val.replace(',','::')    # return:'a::b:: guido'
#删除空格
val.replace(' ','')     #return: 'a,b,guido'

8.2 正则表达式

正则表达式(通常称作regex)提供了一种灵活的文本中搜索或匹配字符串模式的方法。正则表达式是根据正则表达式语言编写的字符串。python内置的re模块负责对字符串应用正则表达式。

re模块的函数可以分为三大类:模式匹配、替换以及拆分。当然它们之间是相辅相成的。一个regex描述了需要在文本中定位的一个模式,它可以用于许多目的。

python之数据的转换及字符串操作_第3张图片

相关代码:

#正则表达式
import re
text="lizihua  come\t  \ton\t  !"
#'\s+'用来描述一个或多个空白符
re.split('\s+',text)    #result:['lizihua', 'come', 'on', '!']
#等效于
regex=re.compile('\s+')
regex.split(text)              #result:['lizihua', 'come', 'on', '!']
#得到匹配regex的所有模式,可以使用findall
regex.findall(text)    #return: ['  ', '\t  \t', '\t  ']
regex.match(text)      #return:None
m=regex.search(text)
#search返回模式在原字符串中起始地址和结束地址,span以及匹配的结果
#return:<_sre.SRE_Match object; span=(7, 9), match='  '>
#但若要只显示结果,则需:
text[m.start():m.end()]  #return:'  '
#将匹配到的模式替换为指定字符串,并返回所得到的新字符串
regex.sub('1',text)    #return:'lizihua1come1on1!'

8.3pandas中矢量化的字符串函数

清理待分析的散乱数据时,常常需要做一些字符串规整化工作。更为复杂的情况是,含有字符串的列有时还含有缺失数据,因此,清理这类散乱数据常用的矢量化字符串方法有:

python之数据的转换及字符串操作_第4张图片

你可能感兴趣的:(数据分析工具,python,异常值的检测和过滤,正则表达式/字符串方法)