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

7.4.2 正则表达式

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

正则表达式是根据正则表达式语言编写的字符串。

re模块的函数可以分为三类:模式匹配;替换;拆分。他们之间相辅相成。

一个regex描述了需要在文本定位的一个模式。

例子:假如想拆分一个字符串,分隔符为数量不定的一组空白符(制表符、空格、换行符)。描述一个或多个空白符的regex是 :\s+

In [57]: import re

In [58]: text="foo bar\t baz \tqux"

In [59]: re.split('\s+',text)

Out[59]: ['foo', 'bar', 'baz', 'qux']

调用re.split('\s+',text)时,正则表达式会先被编译,然后再在text上调用其split方法。

可以用re.compile自己编译regex以得到一个可重用的regex对象:

In [60]: regex=re.compile('\s+')

In [61]: regex.split(text)

Out[61]: ['foo', 'bar', 'baz', 'qux']

如果只希望匹配到regex的所有模式,可以使用findall方法

In [62]: regex.findall(text)

Out[62]: [' ', '\t ', ' \t']

如果想对许多字符串应用同一条正则表达式,建议通过re.compile创建regex对象。节省CPU时间。

findall返回的是字符串中所有的匹配项,而search则只返回第一个匹配项。

match更严格,只匹配字符串的首部。

例子,假设我们有一段文本和一段能识别大部分电子邮件的地址的正则表达式。

In [63]: text = """Dave [email protected]

...: Steve [email protected]

...: Rob [email protected]

...: Ryan [email protected]

...: """

In [64]: pattern=r'[A-Z0-9._%+-]+@[A-Z0-9._]+\.[A-Z]{2,4}'

#re.IGNORECASE的作用是使得正则表达式对于大小写不敏感

In [65]: regex=re.compile(pattern,flags=re.IGNORECASE)

In [68]: regex.split(text)

Out[68]: ['Dave ', '\nSteve ', '\nRob ', '\nRyan ', '\n']

#text使用fillall得到一组电子邮件地址

In [69]: regex.findall(text)

Out[69]: ['[email protected]', '[email protected]', '[email protected]', '[email protected]']

#search返回的是文本中的第一个电子邮件地址

In [70]: m=regex.search(text)

In [71]: m

Out[71]: <_sre.SRE_Match at 0xb992e68>

#对于regex,匹配项对象只能告诉我们模式在原始字符串中的开始和结束位置

In [72]: text[m.start():m.end()]

Out[72]: '[email protected]'

In [74]: regex.match(text)

#regex返回None,因为它只匹配出现在字符串开头的模式

In [75]: print regex.match(text)

None

#sub方法将匹配到的模式替换为指定的字符串,并返回所得到的新字符串

In [76]: regex.sub('RECACTED',text)

Out[76]: 'Dave RECACTED\nSteve RECACTED\nRob RECACTED\nRyan RECACTED\n'

In [77]: print regex.sub('RECACTED',text)

Dave RECACTED

Steve RECACTED

Rob RECACTED

Ryan RECACTED

#将地址分为用户名、域名、以及域后缀,将分段模式括号括起来

In [78]: pattern=r'([A-Z0-9._%+-]+)@([A-Z0-9._]+)\.([A-Z]{2,4})'

In [79]: regex=re.compile(pattern,flags=re.IGNORECASE)

#通过groups方法返回一个由模式各段组成的元组

In [80]: m=regex.match('[email protected]')

In [81]: m.groups()

Out[81]: ('wesm', 'bright', 'net')

#对于带有分组功能的模式,findall会返回一个元组列表

In [82]: regex.findall(text)

Out[82]:

[('dave', 'google', 'com'),

('steve', 'gmail', 'com'),

('rob', 'gmail', 'com'),

('ryan', 'yahoo', 'com')]

#sub还能通过\1 、 \2 之类的特殊符号访问各项匹配项中的分组

In [83]: print regex.sub(r'Username:\1,Domain:\2,Suffix:\3',text)

Dave Username:dave,Domain:google,Suffix:com

Steve Username:steve,Domain:gmail,Suffix:com

Rob Username:rob,Domain:gmail,Suffix:com

Ryan Username:ryan,Domain:yahoo,Suffix:com

In [84]: regex=re.compile(r"""(?P[A-Z0-9._%+-]+)@(?P[A-Z0-9._]+)\.(?P[A-Z]{2,4})""",flags=re.IGNORECASE|re.VERBOSE)

#产生了一个带有分组名称的字典

In [85]: m=regex.match('[email protected]')

In [86]: m.groupdict()

Out[86]: {'domain': 'bright', 'suffix': 'net', 'username': 'wesm'}

利用python进行数据分析之数据规整化(三)_第1张图片

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

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

有时候情况复杂,含有字符串的列有时还含有缺失数据:

In [90]: data = {'Dave':'[email protected]','Steve':'[email protected]','Rob':'[email protected]','Web':np.nan}

In [91]: data=Series(data)

In [92]: data

Out[92]:

Dave    [email protected]

Rob    [email protected]

Steve  [email protected]

Web    NaN

dtype: object

In [93]: data.isnull()

Out[93]:

Dave  False

Rob  False

Steve False

Web  True

dtype: bool

所有的字符串和正则表达式都能被应用于各个值,如果存在NA就会报错。为了解决这个问题,Series有一些能够跳过NA值的字符串操作方法,通过Series的str属性就可以访问这些方法。

In [94]: data.str.contains('gmail')

Out[94]:

Dave  False

Rob  True

Steve True

Web  NaN

dtype: object

In [95]: pattern='([A-Z0-9._%+-]+)@([A-Z0-9._]+)\\.([A-Z]{2,4})'

In [97]: data.str.findall(pattern,flags=re.IGNORECASE)

Out[97]:

Dave [(dave, google, com)]

Rob [(rob, gmail, com)]

Steve [(steve, gmail, com)]

Web NaN

dtype: object

#两个方法可以实习矢量化,使用str.get或者在str属性上面使用索引

In [98]: matches=data.str.match(pattern,flags=re.IGNORECASE)

__main__:1: FutureWarning: In future versions of pandas, match will change to always return a bool indexer.

In [99]: matches

Out[99]:

Dave (dave, google, com)

Rob (rob, gmail, com)

Steve (steve, gmail, com)

Web NaN

dtype: object

In [100]: matches.str.get(1)

Out[100]:

Dave  google

Rob  gmail

Steve gmail

Web  NaN

dtype: object

In [101]: matches.str[0]

Out[101]:

Dave  dave

Rob  rob

Steve steve

Web  NaN

dtype: object

#对字符串进行截取

In [102]: data.str[:5]

Out[102]:

Dave  dave@

Rob  rob@g

Steve steve

Web  NaN

dtype: object

利用python进行数据分析之数据规整化(三)_第2张图片

7.5 示例:USDA视频数据库

利用python进行数据分析之数据规整化(三)_第3张图片

In [219]: import numpy as np

...: import pandas as pd

...: from pandas import Series,DataFrame

...: import matplotlib.pyplot as plt

...: import json

...: import re

#加载json数据

In [220]: db=json.load(open(r"F:\pydata-book-master\ch07\foods-2011-10-03.json"))

...: len(db)

Out[220]: 6636

#查看db这个数据里面有多少个keys

In [221]: db[0].keys()

Out[221]:

[u'portions',

u'description',

u'tags',

u'nutrients',

u'group',

u'id',

u'manufacturer']

#对其中的nutrients单独显示

In [222]: db[0]['nutrients'][0]

...:

Out[222]:

{u'description': u'Protein',

u'group': u'Composition',

u'units': u'g',

u'value': 25.18}

In [223]: nutrients=DataFrame(db[0]['nutrients'])

...:

In [224]: nutrients[:7]

...:

Out[224]:

description        group units    value

0                      Protein  Composition    g    25.18

1            Total lipid (fat)  Composition    g    29.20

2  Carbohydrate, by difference  Composition    g    3.06

3                          Ash        Other    g    3.28

4                      Energy      Energy  kcal  376.00

5                        Water  Composition    g    39.28

6                      Energy      Energy    kJ  1573.00

#我们将取出食物名称,分类,编号和制造商信息

In [225]: info_keys=['description','group','id','manufacturer']

...: info=DataFrame(db,columns=info_keys)

...: info[:5]

...:

Out[225]:

description                  group    id  \

0                    Cheese, caraway  Dairy and Egg Products  1008

1                    Cheese, cheddar  Dairy and Egg Products  1009

2                        Cheese, edam  Dairy and Egg Products  1018

3                        Cheese, feta  Dairy and Egg Products  1019

4  Cheese, mozzarella, part skim milk  Dairy and Egg Products  1028

manufacturer

0

1

2

3

4

#查看食物分类情况

In [226]: pd.value_counts(info.group)[:10]

...:

Out[226]:

Vegetables and Vegetable Products    812

Beef Products                        618

Baked Products                      496

Breakfast Cereals                    403

Legumes and Legume Products          365

Fast Foods                          365

Lamb, Veal, and Game Products        345

Sweets                              341

Fruits and Fruit Juices              328

Pork Products                        328

Name: group, dtype: int64

#为nutrients添加一列id

In [227]: nutrients = []

...:

...: for rec in db:

...:    fnuts = DataFrame(rec['nutrients'])

...:    fnuts['id'] = rec['id']  #广播

...:    nutrients.append(fnuts)

...:

...:

...: nutrients = pd.concat(nutrients,ignore_index = True)

In [228]: nutrients[:5]

...:

Out[228]:

description        group units  value    id

0                      Protein  Composition    g  25.18  1008

1            Total lipid (fat)  Composition    g  29.20  1008

2  Carbohydrate, by difference  Composition    g    3.06  1008

3                          Ash        Other    g    3.28  1008

4                      Energy      Energy  kcal  376.00  1008

#检查重复的列

In [229]: nutrients.duplicated().sum()

...:

Out[229]: 14179

#直接丢弃重复的数据

In [230]: nutrients=nutrients.drop_duplicates()

...: nutrients.duplicated().sum()

Out[230]: 0

In [231]: col_mapping={'description':'food','group':'fgroup'}

...: info=info.rename(columns=col_mapping,copy=False)

...: info[:5]

Out[231]:

food                  fgroup    id  \

0                    Cheese, caraway  Dairy and Egg Products  1008

1                    Cheese, cheddar  Dairy and Egg Products  1009

2                        Cheese, edam  Dairy and Egg Products  1018

3                        Cheese, feta  Dairy and Egg Products  1019

4  Cheese, mozzarella, part skim milk  Dairy and Egg Products  1028

manufacturer

0

1

2

3

4

In [232]: col_mapping={'description':'nutrient','group':'nutgroup'}

...: nutrients=nutrients.rename(columns=col_mapping,copy=False)

...: nutrients[:5]

Out[232]:

nutrient    nutgroup units  value    id

0                      Protein  Composition    g  25.18  1008

1            Total lipid (fat)  Composition    g  29.20  1008

2  Carbohydrate, by difference  Composition    g    3.06  1008

3                          Ash        Other    g    3.28  1008

4                      Energy      Energy  kcal  376.00  1008

#将col_mapping和ifo两个表合并起来

In [233]: ndata=pd.merge(nutrients,info,on='id',how='outer')

...: len(ndata)

Out[233]: 375176

In [234]: ndata[:5]

...:

Out[234]:

nutrient    nutgroup units  value    id  \

0                      Protein  Composition    g  25.18  1008

1            Total lipid (fat)  Composition    g  29.20  1008

2  Carbohydrate, by difference  Composition    g    3.06  1008

3                          Ash        Other    g    3.28  1008

4                      Energy      Energy  kcal  376.00  1008

food                  fgroup manufacturer

0  Cheese, caraway  Dairy and Egg Products

1  Cheese, caraway  Dairy and Egg Products

2  Cheese, caraway  Dairy and Egg Products

3  Cheese, caraway  Dairy and Egg Products

4  Cheese, caraway  Dairy and Egg Products

In [235]: ndata.ix[30000]

...:

Out[235]:

nutrient                                      Glycine

nutgroup                                  Amino Acids

units                                                g

value                                            0.04

id                                                6158

food            Soup, tomato bisque, canned, condensed

fgroup                      Soups, Sauces, and Gravies

manufacturer

Name: 30000, dtype: object

In [236]: result=ndata.groupby(['nutrient','fgroup'])['value'].quantile(0.5)

...:

In [237]: result['Zinc, Zn'].order().plot(kind='barh')

...:

__main__:1: FutureWarning: order is deprecated, use sort_values(...)

Out[237]:

利用python进行数据分析之数据规整化(三)_第4张图片

In [238]: by_nutrient=ndata.groupby(['nutgroup','nutrient'])

...:

In [239]: get_maximum=lambda x: x.xs(x.value.idxmax())

...: get_minimum=lambda x: x.xs(x.value.idxmin())

In [240]: max_foods=by_nutrient.apply(get_maximum)[['value','food']]

...:

#让food小一点

In [241]: max_foods.food=max_foods.food.str[:50]

...:

In [242]: max_foods.ix['Amino Acids']['food']

...:

Out[242]:

nutrient

Alanine                          Gelatins, dry powder, unsweetened

Arginine                              Seeds, sesame flour, low-fat

Aspartic acid                                  Soy protein isolate

Cystine                Seeds, cottonseed flour, low fat (glandless)

Glutamic acid                                  Soy protein isolate

Glycine                          Gelatins, dry powder, unsweetened

Histidine                Whale, beluga, meat, dried (Alaska Native)

Hydroxyproline    KENTUCKY FRIED CHICKEN, Fried Chicken, ORIGINA...

Isoleucine        Soy protein isolate, PROTEIN TECHNOLOGIES INTE...

Leucine          Soy protein isolate, PROTEIN TECHNOLOGIES INTE...

Lysine            Seal, bearded (Oogruk), meat, dried (Alaska Na...

Methionine                    Fish, cod, Atlantic, dried and salted

Phenylalanine    Soy protein isolate, PROTEIN TECHNOLOGIES INTE...

Proline                          Gelatins, dry powder, unsweetened

Serine            Soy protein isolate, PROTEIN TECHNOLOGIES INTE...

Threonine        Soy protein isolate, PROTEIN TECHNOLOGIES INTE...

Tryptophan        Sea lion, Steller, meat with fat (Alaska Native)

Tyrosine          Soy protein isolate, PROTEIN TECHNOLOGIES INTE...

Valine            Soy protein isolate, PROTEIN TECHNOLOGIES INTE...

Name: food, dtype: object

你可能感兴趣的:(利用python进行数据分析之数据规整化(三))