第7章 数据规整化:清理、转换、合并、重塑(5)

来源:互联网 发布:正在优化social club 编辑:程序博客网 时间:2024/05/18 01:08

第7章 数据规整化:清理、转换、合并、重塑(5)

数据转换

前部分都是数据的重排,对数据的处理还包括过滤,清理等。

移除重复数据

  • duplicated()
  • drop_duplicates()
data = DataFrame({'k1':['one']*3+['two']*4,'k2':[1,1,2,3,3,4,4]})Out[126]:     k1  k20  one   11  one   12  one   23  two   34  two   35  two   46  two   4###返回布尔型Series,表示各行是否重复data.duplicated()Out[127]: 0    False1     True2    False3    False4     True5    False6     Truedtype: bool####返回移除重复行的DataFramedata.drop_duplicates() ###注意索引的保留Out[128]:     k1  k20  one   12  one   23  two   35  two   4###duplicated/drop_duplicates默认判断全部列,可以指定部分列进行重复项判断data['v1'] = range(7)Out[130]:     k1  k2  v10  one   1   01  one   1   12  one   2   23  two   3   34  two   3   45  two   4   56  two   4   6data.drop_duplicates(['k1']) ###仅判断k1列中的重复元素Out[133]:     k1  k2  v10  one   1   03  two   3   3####此处书上错误####duplicated/drop_duplicates默认保留第一个出现的值的组合,keep参数可以控制保留项####keep三个参数,'first' 'last' False,默认为'first',为False是删除所有重复项,first/last分别是删除重复项但保留第一个/最后一个出现的重复项data.drop_duplicates(['k1','k2'],keep = 'last')Out[135]:     k1  k2  v11  one   1   12  one   2   24  two   3   46  two   4   6

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

data = DataFrame({'food':['bacon','pulled pork','bacon','Pastrami','corned beef','Bacon','pastrami','honey ham','nova lox'],'ounces':[4,3,12,6,7.5,8,3,5,6]})Out[137]:           food  ounces0        bacon     4.01  pulled pork     3.02        bacon    12.03     Pastrami     6.04  corned beef     7.55        Bacon     8.06     pastrami     3.07    honey ham     5.08     nova lox     6.0####肉类到动物的映射##字典存储映射meat_to_animal={'bacon':'pig','pulled pork':'pig','pastrami':'cow','corned beef':'cow','honey ham':'pig','nova lox':'Salmon'}###Series中map方法可以接受一个函数或含有映射关系的字典型对象,对Series中每个元素处理####注意先处理大小写问题,str.lower####或者引入lamda。 data['animal'] = data['food'].map(lamda x: meat_to_animal[x.lower()])data['animal'] = data['food'].map(str.lower).map(meat_to_animal)

替换值

  • fillna填充缺失数据
  • map修改对象的数据子集
  • replace
data = Series([1,-999,2,-999,-1000,3]) ##-999代表数据缺失的标记值。要将其替换为NANdata.replace(-999,np.nan)###用np.nan替换-999data.replace([-999,-1000],np.nan)####一次替换多个值,-999和-1000都替换为NANdata.replace([-999,-1000],[np.nan,0])####一一对应替换 -999→NAN,-1000→0data.replace({-999:np.nan,-1000:0}) ####传入字典参数

重命名轴索引

与Series一样,轴标签中的元素也可以通过函数或者映射进行转换,从而得到新对象。

data = DataFrame(np.arange(12).reshape(3,4),index=['Ohio','Colorado','New York'],columns=['one','two','three','four'])data.index = data.index.map(str.upper) ###index中字符全替换为大写再赋值回去date_new = data.rename(index = str.title,columns=str.upper)##创建转化后的新的数据集,保留原始数据####str.title将字符串转化为标题版本,即首字母大写,其余小写###rename结合字典可以对部分轴标签更新data_new2 = data.rename(index={'OHIO':'IDIANA'},columns={'three':'peekaboo'})Out[154]:           one  two  peekaboo  fourIDIANA      0    1         2     3COLORADO    4    5         6     7NEW YORK    8    9        10    11####rename就地修改,直接修改源数据,不返回新数据_ = data.rename(index={'OHIO':'INDIANA'},inplace = True)In [158]:dataOut[158]:           one  two  three  fourINDIANA     0    1      2     3COLORADO    4    5      6     7NEW YORK    8    9     10    11

离散化和区间划分

连续数据的拆分

ages = [20,22,25,27,21,23,37,31,61,45,41,32]bins = [18,25,35,60,100] ##设定划分区间18-25,26-35,36-60,61-100cats = pd.cut(ages,bins) ##返回一个Categorical对象,默认区间为左开右闭,通过right参数来调整,right = False为左闭右开,默认right = TrueIn [164]:catsOut[164]: [(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]Length: 12Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]###对Categorical对象的描述与书上有不同####Categorical对象由两个部分组成,一个是划分的区间,还有一个是原数据划分后的结果,其中有两个属性,Categorical.categories(返回划分的区间,并表明闭区间在左侧还是右侧)和Categorical.codes(表明原数据中每个数据所处的区间,用划分区间的下标索引表示,从0开始)In [169]:cats.categoriesOut[169]: IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]]              closed='right',              dtype='interval[int64]')In [170]:cats.codesOut[170]: array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)####给每个区间计数In [172]:pd.value_counts(cats)Out[172]: (18, 25]     5(35, 60]     3(25, 35]     3(60, 100]    1dtype: int64####可以给每个区间设定一个名称,通过labels参数传入每个区间的名字group_name = ['Youth','YoungAdult','MiddleAged','Senior']pd.cut(ages,bins,labels = group_name)Out[175]: [Youth, Youth, Youth, YoungAdult, Youth, ..., YoungAdult, Senior, MiddleAged, MiddleAged, YoungAdult]Length: 12Categories (4, object): [Youth < YoungAdult < MiddleAged < Senior]###如果传入的是区间数量而不是确切边界,则会根据数据最小值和最大值,计算等长区间data = np.random.randn(20)pd.cut(data,4,precision = 2)###设置区间边界精度Out[182]: [(0.99, 1.94], (-1.87, -0.91], (-0.91, 0.037], (0.037, 0.99], (0.99, 1.94], ..., (0.99, 1.94], (0.99, 1.94], (-1.87, -0.91], (-0.91, 0.037], (-1.87, -0.91]]Length: 20Categories (4, interval[float64]): [(-1.87, -0.91] < (-0.91, 0.037] < (0.037, 0.99] < (0.99, 1.94]]######qcut与cut类似,但是是根据样本分位数对数据进行区间划分,cut可能无法使区间内含有相同数量的数据,但是qcut可以获得数量基本相同的区间data = np.random.randn(1000)cats = pd.qcut(data,4) ####按四分位数进行划分Out[184]: [(0.606, 2.823], (-0.683, -0.0468], (-0.683, -0.0468], (-0.0468, 0.606], (0.606, 2.823], ..., (-0.683, -0.0468], (-3.382, -0.683], (0.606, 2.823], (-3.382, -0.683], (0.606, 2.823]]Length: 1000Categories (4, interval[float64]): [(-3.382, -0.683] < (-0.683, -0.0468] < (-0.0468, 0.606] < (0.606, 2.823]]In [186]:pd.value_counts(cats)Out[186]: (0.606, 2.823]       250(-0.0468, 0.606]     250(-0.683, -0.0468]    250(-3.382, -0.683]     250dtype: int64###可自定义分位数,0-1之间的数值,包含端点new_cats = pd.qcut(data,[0,0.1,0.5,0.9,1])In [188]:pd.value_counts(new_cats)Out[188]: (-0.0468, 1.206]     400(-1.329, -0.0468]    400(1.206, 2.823]       100(-3.382, -1.329]     100dtype: int64

检测过滤异常值

异常值即孤立点、离群点

data = DataFrame(np.random.randn(1000,4)) ###生成4列,每列都是正态分布数的DataFrame对象In [190]:data.describe() ####data属性Out[190]:                  0            1            2            3count  1000.000000  1000.000000  1000.000000  1000.000000mean      0.036955    -0.030808     0.004385     0.017893std       1.005653     0.979606     1.003002     0.999522min      -3.400193    -3.871381    -3.626467    -3.56184625%      -0.634620    -0.667826    -0.718142    -0.68181250%       0.038195    -0.050365    -0.040234     0.02488275%       0.768188     0.602451     0.684530     0.682487max       2.859131     3.395861     3.192252     3.020070col = data[3]In [192]:col[np.abs(col)>3]   ###找出3列中绝对值大于3的值Out[192]: 29     3.020070279   -3.055511500   -3.561846711   -3.541687Name: 3, dtype: float64###找出全部含有绝对值大于3的值的行data[(np.abs(data)>3).any(axis = 1)] ###设定any方法中的axis = 1表示每行中含有绝对值大于3的值Out[197]:             0         1         2         317  -0.748195 -3.159036 -0.404608  0.90449829  -0.164734 -1.256519 -0.724999  3.020070109  0.452139 -1.042520  3.143075  1.048354279 -1.958829  0.087400 -0.392875 -3.055511392  0.045182  2.131359 -3.445043  0.416538500 -2.099903 -1.963188 -0.240716 -3.561846556 -0.600726  0.470719 -3.626467 -0.585577576 -0.460733  0.562222  3.192252 -1.666503682 -0.716962  3.395861  0.047119  0.173432711 -0.473312 -0.193344  1.278363 -3.541687751 -3.110940  0.388629 -0.221459  0.790747769  0.416308 -3.653692  1.500504 -0.837095840 -3.400193  1.916887 -1.275942  0.483493887  0.159239  1.655584 -3.086544 -0.213076959  0.227707  3.008310  0.691871  0.501017967  0.304056 -3.871381 -1.409443  0.430060####限制data中所有值在[-3,3]data[np.abs(data)>3]=np.sign(data)*3 ###返回符号 ±,sign(-3)=-1,sign(3)=1In [203]:data.describe()Out[203]:                  0            1            2            3count  1000.000000  1000.000000  1000.000000  1000.000000mean      0.037466    -0.029528     0.005207     0.019032std       1.004020     0.972518     0.998189     0.995644min      -3.000000    -3.000000    -3.000000    -3.00000025%      -0.634620    -0.667826    -0.718142    -0.68181250%       0.038195    -0.050365    -0.040234     0.02488275%       0.768188     0.602451     0.684530     0.682487max       2.859131     3.000000     3.000000     3.000000

排列和随机采样

  • numpy.random.permutation
df = DataFrame(np.arange(20).reshape(5,4))sampler = np.random.permutation(5)####返回一个随机排列的数列,或者范围内的随机排列的数列,如果传入参数是个多维ndarray,则沿着第一个索引随机排列,即二维数组,沿着行的索引随机排列###shuffle有相同效果,但是只接受array_like,不能接受int,且不返回打乱后的数组,是inplace修改In [207]:samplerOut[207]: array([3, 1, 2, 0, 4])df.take(sampler)####沿着轴返回给定顺寻索引的dataframe数据,默认axis=0Out[208]:     0   1   2   33  12  13  14  151   4   5   6   72   8   9  10  110   0   1   2   34  16  17  18  19df.take(np.random.permutation(len(df))[:3])###切取permutation生成的随机排列array的前三个,再按照索引顺序切取df数据Out[209]:     0   1   2   31   4   5   6   73  12  13  14  154  16  17  18  19bag = np.array([5,7,-1,6,4])sampler = np.random.randint(low = 0,high = len(bag),size = 10)###randint(最小值,最大值,个数)Out[212]: array([2, 2, 0, 4, 2, 2, 1, 4, 1, 3])draws = bag.take(sampler)Out[214]: array([-1, -1,  5,  4, -1, -1,  7,  4,  7,  6])

计算指标/哑变量

  • get_dummies
df = DataFrame({'key':['b','b','a','c','a','b'],'data1':range(6)})Out[220]:    data1 key0      0   b1      1   b2      2   a3      3   c4      4   a5      5   bpd.get_dummies(df['key'])####哑矩阵将传入参数不同种类展开为不同列,例子中abc展开,矩阵中只有0,1两个值,0代表非,1代表是Out[221]:    a  b  c0  0  1  01  0  1  02  1  0  03  0  0  14  1  0  05  0  1  0####给哑矩阵每个列加一个前缀名,参数prefix控制dummies = pd.get_dummies(df['key'],prefix = 'key')Out[223]:    key_a  key_b  key_c0      0      1      01      0      1      02      1      0      03      0      0      14      1      0      05      0      1      0#####与df['data1']合并为一个DataFramedf_with_dummy = df[['data1']].join(dummies)Out[225]:    data1  key_a  key_b  key_c0      0      0      1      01      1      0      1      02      2      1      0      03      3      0      0      14      4      1      0      05      5      0      1      0####dummies和cut结合可以清晰展示每个数据的区间values = np.random.rand(10)Out[227]: array([ 0.39412391,  0.07717691,  0.5872264 ,  0.25836265,  0.2311182 ,        0.93356344,  0.16665829,  0.96166322,  0.13581445,  0.80504075])bins = [0,0.2,0.4,0.6,0.8,1]pd.get_dummies(pd.cut(values,bins))Out[229]:    (0.0, 0.2]  (0.2, 0.4]  (0.4, 0.6]  (0.6, 0.8]  (0.8, 1.0]0           0           1           0           0           01           1           0           0           0           02           0           0           1           0           03           0           1           0           0           04           0           1           0           0           05           0           0           0           0           16           1           0           0           0           07           0           0           0           0           18           1           0           0           0           09           0           0           0           0           1

字符串操作

val = 'a,b, guido'val.split(',')###逗号分隔字符串Out[232]: ['a', 'b', ' guido']pieces = [x.strip() for x in val.split(',')]###strip()剪去空白符,包括换号符等Out[234]: ['a', 'b', 'guido']'::'.join(pieces)###用"::"连接pieces中的字符串Out[235]: 'a::b::guido''guido' in val ###判断是否包含子串Out[236]: Trueval.index(',')####返回第一个出现','符号的位置Out[237]: 1val.find(':')###在val中找':'Out[238]: -1val.count(',')##返回','出现的次数Out[239]: 2val.replace(',','::')###用'::'替换',',传入空字符串可以执行删除操作Out[240]: 'a::b:: guido'

Python内置字符串方法

方法 说明 count 返回子串在字符串中出现的次数 endswith、startswith 如果字符串以某个后缀结尾(以某个前缀开头),则返回True join 字符串连接 index 如果在字符串中找到子串,则返回子串第一个字符所在的位置,如果没找到引发异常 find 如果在字符串中找到子串,则返回子串第一个字符所在的位置,如果没找到返回-1 rfind 如果在字符串中找到子串,则返回最后一个发现的子串第一个字符所在的位置,如果没找到返回-1 replace 替换 strip、rstrip、lstrip 去除空白符 split 用制定分隔符拆分字符串 lower、upper 字母大小写转换 ljust、rjust 用空格(或其他字符)填充字符串空白侧以返回符合最低宽度的字符串
阅读全文
0 0
原创粉丝点击