欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-01 11:29:02
...

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

一、移除重复数据

  • 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之数据的转换及字符串操作

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

相关代码:

#字符串操作:
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之数据的转换及字符串操作

相关代码:

#正则表达式
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之数据的转换及字符串操作