【Python数据分析基础笔记(仅供本人学习记录)】P7.用pandas进行数据预处理

8.用数据进行数据预处理

8.1数据清洗

    在数据分析前,首先要进行数据采集。通常,采集到的原始数据大多数是不完整和不一致的“脏”数据,无法直接进行数据挖掘。为了提高挖掘质量,产生了数据预处理技术。数据预处理包括数据清洗,数据集成,数据变换,数据归约等。
    数据清洗是发现并纠正数据文件中可识别的错误,如移除重复数据,处理缺失值和空格值,检测和过滤异常值,并检查数据一致性等。通过数据清洗不仅要使通过清洗后的数据变的可用,而且还要使数据变的更加适合进行后续的数据分析工作。

8.1.1重复值处理

    数据采集所获得的原始数据集中,往往会存在着许多重复数据。所谓重复数据是指在数据结构中所有列的内容都相同,即行重复。而处理重复数据是数据分析中经常要面对的问题之一。

pandas提供了duplicated()drop_duplicates()函数可用于标记及删除重复数据。

  • 1、duplicated()函数
    duplicated()函数用于标记Series中的值、DataFrame中的记录行是否是重复,重复为True,不重复为False。

语法格式如下:

pandas.DataFrame.duplicated(subset=None,keep='first')或pandas.Series.duplicated(keep='first')

参数说明:

  • subset:接收特定的string或sequence,用于识别重复的列标签或列标签序列,默认为列标签,默认值为None

  • keep:接收特定的string,first表示除了第一次出现外,其余相同的重复项标记为True;last表示除了最后一次出现外,其余相同的重复项标记为True,False表示将所有的重复项标记为True,默认为first。

  • 2、drop_duplicates()函数
    drop_duplicates()函数用于删除Series、DataFrame中重复记录,并返回删除重复后的结果

语法格式如下:

pandas.DataFrame.drop_duplicates(subset=None,keep='first',inplace=False)或pandas.Series.drop_duplicates(keep='first',inplace=False)

参数说明:

  • subset:接收string或sequence,仅考虑用于标识重复项的某些列,默认情况下使用列。默认值为None
  • keep:接收特定的string,first表示删除重复项并保留第一次出现的项;last表示除了最后一次出现外,其余相同的重复项标记为True,False表示将所有的重复项标记为True,默认为first。
  • inplace:接收boolean,True表示直接修改原对象,False表示创建一个副本,修改副本,原对象不变,默认为False

【例】有一个手机评论数据Mobile.csv文件,改文件的数据列包括手机品牌、价格和评分。现在要求完成去除改文件中的重复值,其示例代码如下:

import pandas as pd
df=pd.read_csv('P:/data/Mobile.csv',encoding='GBK',low_memory=False)
print('原数据为:')
df
原数据为:
Samsung199.9951Unnamed: 4Unnamed: 5Unnamed: 6Unnamed: 7Unnamed: 8Unnamed: 9...Unnamed: 11Unnamed: 12Unnamed: 13Unnamed: 14Unnamed: 15Unnamed: 16Unnamed: 17Unnamed: 18Unnamed: 19Unnamed: 20
0Samsung199.9940NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1Samsung199.9940NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
2Samsung199.9911NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
3Samsung199.9920NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
4Samsung199.9920NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
..................................................................
327586Samsung79.9550NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
327587Samsung79.9530NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
327588Samsung79.9550NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
327589Samsung79.9530NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
327590Samsung79.9540NaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN

327591 rows × 21 columns

补充:iloc参数用法:.loc先行后列,中间用逗号(,)分割https://www.py.cn/faq/python/18973.html

#取df中0-4列数据
df1=df.iloc[:,0:4]
print(df1)
        Samsung  199.99  5  1
0       Samsung  199.99  4  0
1       Samsung  199.99  4  0
2       Samsung  199.99  1  1
3       Samsung  199.99  2  0
4       Samsung  199.99  2  0
...         ...     ... .. ..
327586  Samsung   79.95  5  0
327587  Samsung   79.95  3  0
327588  Samsung   79.95  5  0
327589  Samsung   79.95  3  0
327590  Samsung   79.95  4  0

[327591 rows x 4 columns]
#标识重复项
data=df1.duplicated(keep='first')
print(data)
0         False
1          True
2         False
3         False
4          True
          ...  
327586     True
327587     True
327588     True
327589     True
327590     True
Length: 327591, dtype: bool
#删除重复项
data1=df1.drop_duplicates(keep='first')
print(data1)
        Samsung  199.99  5    1
0       Samsung  199.99  4    0
2       Samsung  199.99  1    1
3       Samsung  199.99  2    0
5       Samsung  199.99  5    0
6       Samsung  199.99  3    0
...         ...     ... ..  ...
327459  Samsung   79.95  5    3
327493  Samsung   79.95  5   16
327498  Samsung   79.95  1    4
327500  Samsung   79.95  5   12
327543  Samsung   79.95  2  NaN

[36830 rows x 4 columns]

8.1.2 缺失值的处理

常见的缺失值处理方式有过滤和填充。在Python中,pandas使用浮点值NaN表示浮点数和非浮点数组中的缺失值,同时Python内置None值也会被当作是缺失值。在处理缺失值之前,首先要判断缺失值是否存在,然后再对缺失值进行删除、填充或者不处理的操作
1.判断缺失值的函数
(1)isnull()函数:用于检查空值或缺失值的对象;如果有空值或缺失值则返回True,否则返回False。     
(2)notnull()函数:用于检查不为空值或缺失值的对象;如果有空值或缺失值则返回False,否则返回True。
 通过isnull()函数和sum()函数可以获得Series和DataFrame中缺失值的数量
2.处理缺失值的方法:

数据缺失值的处理方法有以下3种

·删除含有缺失值的记录

·进行数据插补

·不处理空值或缺失值

(1)删除含有缺失值的记录
在数据分析中,如果数据集的样本很大,并且在删除含有缺失值的记录后,不会影响分析结果的客观性和准确性时,一般是使用dropna()函数直接将空值或缺失值的数据删除

dropna()函数的语法格式如下: DataFrame.dropna(axis=0,how='any',thresh=None,subset=None,inplace=False)
参数说明:

  • axis:指定删除方向,axis=0按行删除,axis=1按列删除,默认为0
  • how:取值为“all”表示这一行或列中的元素全部缺少(为NaN)才删除这一行或列;取值为“any”表示这一行或列中只要有缺失值,就删除这一行或列
  • thesh:一行或一列中至少出现了thesh个才删除
  • subset:在某些列的子集中选择了缺失值的列删除,不在子集中的含有缺失值的行或列不会被删除
  • inplace:筛选缺失值后,获得的新数据是存为副本还是直接在原数据上修改

【例】:导入Excel成绩表grade.xls中的grade1表,完成各种不同情况下删除缺失值的操作,其示例代码如下:

import pandas as pd
#导入成绩数据
df=pd.read_excel('p:/data/grade.xls',sheet_name='grade1')
df
stu_idNormalexam
0201700180.066.0
12017002NaNNaN
22017003NaN60.0
3201700487.0NaN
42017005NaNNaN
52017006NaN76.0
6201700787.0NaN
7201700890.083.0
82017009NaN80.0
9201701090.0NaN
10201701175.0NaN
11201701270.0NaN
12201701381.062.0
13201701486.083.0
14201701587.074.0
152017016NaN82.0
16201701784.060.0
172017018NaNNaN
18201701991.085.0
19201702086.061.0
20201702191.081.0
212017022NaNNaN
22201702395.081.0
23201702488.091.0
24201702588.084.0
25201702691.080.0
26201702791.089.0
27201702890.083.0
28201702988.068.0
29201703074.047.0
30201703181.050.0
31201703278.048.0
32201703381.060.0
33201703484.089.0
34201703587.079.0
35201703682.070.0
36201703789.060.0
37201703890.064.0
#所有值全为缺失值才删除
df1=df.dropna(how='all')
#输出df1的前5行
print(df1.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002     NaN   NaN
2  2017003     NaN  60.0
3  2017004    87.0   NaN
4  2017005     NaN   NaN
#删除至少出现过两个缺失值的行
df1=df.dropna(thresh=2,axis=0)
df1
stu_idNormalexam
0201700180.066.0
22017003NaN60.0
3201700487.0NaN
52017006NaN76.0
6201700787.0NaN
7201700890.083.0
82017009NaN80.0
9201701090.0NaN
10201701175.0NaN
11201701270.0NaN
12201701381.062.0
13201701486.083.0
14201701587.074.0
152017016NaN82.0
16201701784.060.0
18201701991.085.0
19201702086.061.0
20201702191.081.0
22201702395.081.0
23201702488.091.0
24201702588.084.0
25201702691.080.0
26201702791.089.0
27201702890.083.0
28201702988.068.0
29201703074.047.0
30201703181.050.0
31201703278.048.0
32201703381.060.0
33201703484.089.0
34201703587.079.0
35201703682.070.0
36201703789.060.0
37201703890.064.0
#输出df1的前10行
print(df.head(10))
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002     NaN   NaN
2  2017003     NaN  60.0
3  2017004    87.0   NaN
4  2017005     NaN   NaN
5  2017006     NaN  76.0
6  2017007    87.0   NaN
7  2017008    90.0  83.0
8  2017009     NaN  80.0
9  2017010    90.0   NaN
#删除subset中指定的列含有缺失值的行
df1=df.dropna(subset=['exam'])
#输出df1的前5行
print(df1.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
2  2017003     NaN  60.0
5  2017006     NaN  76.0
7  2017008    90.0  83.0
8  2017009     NaN  80.0
#删除含有缺失值的列
print(df.dropna(axis=1))
     stu_id
0   2017001
1   2017002
2   2017003
3   2017004
4   2017005
5   2017006
6   2017007
7   2017008
8   2017009
9   2017010
10  2017011
11  2017012
12  2017013
13  2017014
14  2017015
15  2017016
16  2017017
17  2017018
18  2017019
19  2017020
20  2017021
21  2017022
22  2017023
23  2017024
24  2017025
25  2017026
26  2017027
27  2017028
28  2017029
29  2017030
30  2017031
31  2017032
32  2017033
33  2017034
34  2017035
35  2017036
36  2017037
37  2017038
#只要有缺失值就删除,并且直接在原数据上修改
df1=df.dropna(how='any',inplace=True)
print(df)
     stu_id  Normal  exam
0   2017001    80.0  66.0
7   2017008    90.0  83.0
12  2017013    81.0  62.0
13  2017014    86.0  83.0
14  2017015    87.0  74.0
16  2017017    84.0  60.0
18  2017019    91.0  85.0
19  2017020    86.0  61.0
20  2017021    91.0  81.0
22  2017023    95.0  81.0
23  2017024    88.0  91.0
24  2017025    88.0  84.0
25  2017026    91.0  80.0
26  2017027    91.0  89.0
27  2017028    90.0  83.0
28  2017029    88.0  68.0
29  2017030    74.0  47.0
30  2017031    81.0  50.0
31  2017032    78.0  48.0
32  2017033    81.0  60.0
33  2017034    84.0  89.0
34  2017035    87.0  79.0
35  2017036    82.0  70.0
36  2017037    89.0  60.0
37  2017038    90.0  64.0
(2)数据插补法
在数据分析中,如果数据集的样本比较少或者由于删除含有缺失值的记录会影响到数据分析结果的客观性和准确性时,就需要根据数据插补的方法来选择填充值,然后再使用fillna()函数对空值或缺失值进行填充。
fill函数格式如下:

DataFrame.fillna(value=None,method=None,axis=None,inplace=False,limit=None,downcast=None,**kwargs)

参数说明:

  • value:接收常数,dict,Series或DataFrame,表示填充缺失值的值
  • method:表示填充缺失值的方法,method的取值为{‘pad’,‘ffill’,‘backfill’,‘bfill’,‘None’}。pad/ffill:用前一个非缺失值去填充该缺失值。backfill/bfill:用下一个非缺失值去填充该缺失值。none:指定一个值去替换缺失值(缺省默认这种方式)
  • axis:指定填充方向,axis=1按列填充,axis=0按行填充
  • inplace:接收True或False。True表示直接修改原对象,False表示创建一个副本,修改副本,原对象不变,默认为False
  • limit:表示限制填充的个数,如果limit=2,则只填充两个缺失值
  • downcast:默认为None,如果需要将填充的值向下转换为适当的相等数据类型的数值,如将float64数据类型转换为int64数据类型时,则此参数的值为“infer”

注意:method参数不能和value参数同时出现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JcGNn9xW-1637637711978)(数据插补方法.jpg)]

【例】导入Excel成绩表grade.xls中的grade1表,完成以下操作

  • (1)查看该表前五行的缺失值,分别用0和字典填充缺失值,但不修改原数据
  • (2)分别指定不同的method参数,观察填充缺失值情况
  • (3)将Normal属性的缺失值用中位数替换,exam属性的缺失值用均值替换
  • (4)用0替换缺失值,并修改原数据
  • 代码如下
import pandas as pd
#导入数据
df=pd.read_excel('p:/data/grade.xls',sheet_name='grade1')
#1.查看前5行
print(df.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002     NaN   NaN
2  2017003     NaN  60.0
3  2017004    87.0   NaN
4  2017005     NaN   NaN
#查看缺失值的数量
print(df.isnull().sum())
stu_id    0
Normal    8
exam      9
dtype: int64
#用0填充
df1=df.fillna(0)
print(df1.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002     0.0   0.0
2  2017003     0.0  60.0
3  2017004    87.0   0.0
4  2017005     0.0   0.0
#用字典填充
df2=df.fillna({'Normal':60,'exam':40})
print(df2.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002    60.0  40.0
2  2017003    60.0  60.0
3  2017004    87.0  40.0
4  2017005    60.0  40.0
#观察原来的数据df没有改变
print(df.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002     NaN   NaN
2  2017003     NaN  60.0
3  2017004    87.0   NaN
4  2017005     NaN   NaN
#指定method='ffill'/'pad':用前一个非缺失值填充该缺失值
df2=df.fillna(method='ffill')
print(df2.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002    80.0  66.0
2  2017003    80.0  60.0
3  2017004    87.0  60.0
4  2017005    87.0  60.0
#指定method = 'bfill'/'backfill':用下一个非缺失值填充该缺失值
df2 = df.fillna(method='bfill')
print(df2.head())

    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002    87.0  60.0
2  2017003    87.0  60.0
3  2017004    87.0  76.0
4  2017005    87.0  76.0
#6.将exam列的缺失值用均值替换
exa_mea = df['exam'].fillna(df['exam'].mean())
print(exa_mea.head())
0    66.000000
1    72.275862
2    60.000000
3    72.275862
4    72.275862
Name: exam, dtype: float64
#将Normal列的缺失值用中位数替换
Nor_med = df['Normal'].fillna(df['Normal'].median())
print(Nor_med.head())

0    80.0
1    87.0
2    87.0
3    87.0
4    87.0
Name: Normal, dtype: float64
#7.指定inplace参数为True
print(df.fillna(0,inplace=True))
None
#观察原来数据df发生改变
print(df.head())
    stu_id  Normal  exam
0  2017001    80.0  66.0
1  2017002     0.0   0.0
2  2017003     0.0  60.0
3  2017004    87.0   0.0
4  2017005     0.0   0.0

8.1.3异常值处理

所谓异常值,就是在数据集中存在不合理的值,又称离群点。例如年龄为负数,成绩大于100或小于零,商品评分超出5分或商品日销售量远远超过年销售量等,都属于异常值的范围。
1. 判别数据集中异常值方法
(1)散点图分析
(2)简单统计分析
   例如,年龄属性值的区间规定为[0:150],如果数据集样本中的年龄值不在该区间范围内,则表示该样本的年龄属性属于异常值。
(3)3δ原则
   3δ原则是指当数据服从正态分布时,根据正态分布的定义可知,距离平均值3δ之外的概率为 P(|x-μ|>3δ) <= 0.003 ,这是属于极小的概率事件, 因此,当样本距离平均值大于3δ时,则认定该样本为异常值。 
(4)箱型图分析
   箱型图提供了一个识别异常值的标准,即大于或小于箱型图设定的上下界的数值即为异常值。
2. 异常值的处理方法
常用的异常值处理方法有以下4种。
(1)删除含有异常值的记录。
(2)将异常值视为缺失值,按照缺失值的处理方法来处理。
(3)用平均值来修正异常值。
(4)对异常值不处理。

在处理异常值时,有些异常值可能含有有用信息,因此,如何判定和处理异常值,需视情况而定。在数据量较多时,可用散点图和描述性的统计来查看数据基本情况,发现异常值,并借助箱线图进行监测

【例】有餐厅销售数据表sale.xls,在该数据表中有日期和销量两列数据,要求分析该数据表中销量数据的异常值,并将异常值用销量数据替换掉

数据分析思路:首先读取文件中的数据,并对销量数据进行描述性统计分析。通过描述性统计分析发现异常值,然后,运用散点图寻找异常值,最后,将异常值用销量数据的中位数替换。代码如下:

8.2 数据合并

通过数据合并,可以将多个数据集整合到一个数据集中,常用的数据合并函数有merge(),join(),concat(),append(),combine_first()

8.2.1按键连接数据

1.merge()函数

在pandas中,通过两个数据集上一个或多个键来合并数据时,可使用merge()函数。函数格式如下:

pandas.merge(left,right,how='inner',on=None,left_on=None,right_on=None,left_index=False,right_index=False,sort=False,suffixes=('_x','_y'),copy=True,indicator=False)

函数参数说明如下:

  • left:参与合并的左侧DataFrame
  • right:参与合并的右侧DataFrame
  • how:表示连接方式,取值{inner,outer,left,right},默认为inner内连接,其结果是取两个数据集中键值交集的数据;outer外连接,其结果是取两个数据集中键值并集的数据,对不匹配的键所对应的数据用NaN填充;left左连接,取左侧全部数据,右侧取与左侧想匹配的键所对应的数据,不匹配的键所对应的数据用NaN填;right右连接,取右侧全部数据,左侧取与右侧相匹配的键所对应的数据,不匹配的键所对应的数据用NaN填充
  • on:表示用于连接的列名,必须同时存在于左右两个DataFrame对象中,如果未传递且left_index和right_index为False,则DataFrame中列的交集将作为连接键
  • left_on:表示左侧的DataFrame中用作连接键的列,可以是列名、索引级名称,也可以是长度等于DataFrame长度的数组
  • right_on:表示左侧的DataFrame中用作连接键的列,可以是列名、索引级名称,也可以是长度等于DataFrame长度的数组
  • left_index:如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键
  • right_index:如果为True,则使用右侧DataFrame中的索引(行标签)作为其连接键
  • suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时,在列名后面附加的后缀名称,默认为(’_x’,’_y’),例如,左右两个DataFrame对象有"data",则结果中就会出现’data_x’和’data_y’
  • copy:默认为True,表示总是将数据复制到数据结构中,大多数情况下设置为False可以提高性能
  • indicator:默认为False,如果设置为True,将显示合并数据中每行来源的信息添加到名为_merge的列中输出,例如,只来自左边(left_only)、两者(both)、只来自右边(right_only)

【例】创建产品信息(info)和产品销售(sale)数据集,并完成下列对产品信息和产品销售数据集的数据合并操作

(1)使用默认连接方式连接产品信息和产品销售数据集

(2)按照指定“产品编号”列名合并产品信息和产品销售数据集

(3)分别用left、right、outer连接方式连接数据集

(4)根据“产品编号”和“品牌”多个键进行连接

(5)对重复的列名处理

(6)将索引作为连接的键

其代码如下:

import pandas as pd
#创建产品信息(info)和产品销售(sale)数据集
info = pd.DataFrame({'产品编号':list('ABCD'),'类型名称':['电视机','手机','电脑','空调'],
                     '品牌':['格力','康佳','海信','TCL']},index=range(1001,1005))
info.columns.name='产品信息'
info.index.name='编号'
print(info)
产品信息 产品编号 类型名称   品牌
编号                 
1001    A  电视机   格力
1002    B   手机   康佳
1003    C   电脑   海信
1004    D   空调  TCL
sale = pd.DataFrame({'产品编号':list('ABECDF'),'品牌':['格力','康佳','海信','TCL','康佳','格力'],
                     '价格':[3600,1500,4500,2000,2300,3500]},index=range(1001,1007))
sale.columns.name='产品销售'
sale.index.name='编号'
print(sale)

产品销售 产品编号   品牌    价格
编号                  
1001    A   格力  3600
1002    B   康佳  1500
1003    E   海信  4500
1004    C  TCL  2000
1005    D   康佳  2300
1006    F   格力  3500
#1.	使用默认连接方式连接产品信息和产品销售数据集
print(pd.merge(info,sale))
#2.	按照指定“产品编号”列名合并产品信息和产品销售数据集
print(pd.merge(info,sale,on='产品编号'))
#3.	分别用left、right、outer连接方式连接数据集。
print(pd.merge(info,sale,how='left'))
print(pd.merge(info,sale,how='right'))
print(pd.merge(info,sale,how='outer'))

  产品编号 类型名称  品牌    价格
0    A  电视机  格力  3600
1    B   手机  康佳  1500
  产品编号 类型名称 品牌_x 品牌_y    价格
0    A  电视机   格力   格力  3600
1    B   手机   康佳   康佳  1500
2    C   电脑   海信  TCL  2000
3    D   空调  TCL   康佳  2300
  产品编号 类型名称   品牌      价格
0    A  电视机   格力  3600.0
1    B   手机   康佳  1500.0
2    C   电脑   海信     NaN
3    D   空调  TCL     NaN
  产品编号 类型名称   品牌    价格
0    A  电视机   格力  3600
1    B   手机   康佳  1500
2    E  NaN   海信  4500
3    C  NaN  TCL  2000
4    D  NaN   康佳  2300
5    F  NaN   格力  3500
  产品编号 类型名称   品牌      价格
0    A  电视机   格力  3600.0
1    B   手机   康佳  1500.0
2    C   电脑   海信     NaN
3    D   空调  TCL     NaN
4    E  NaN   海信  4500.0
5    C  NaN  TCL  2000.0
6    D  NaN   康佳  2300.0
7    F  NaN   格力  3500.0
#4.根据产品编号和品牌多个键进行连接
print(pd.merge(info,sale,on=['产品编号','品牌']))
#5.对重复的列名进行处理
print(pd.merge(info,sale,on='产品编号',suffixes=('_1','_2')))
#6.将索引作为连接的键
print(pd.merge(info,sale,on=['产品编号','品牌']))
  产品编号 类型名称  品牌    价格
0    A  电视机  格力  3600
1    B   手机  康佳  1500
  产品编号 类型名称 品牌_1 品牌_2    价格
0    A  电视机   格力   格力  3600
1    B   手机   康佳   康佳  1500
2    C   电脑   海信  TCL  2000
3    D   空调  TCL   康佳  2300
  产品编号 类型名称  品牌    价格
0    A  电视机  格力  3600
1    B   手机  康佳  1500

2.join()函数

除了merge()函数外,还可以使用join()函数来实现根据特定的列和索引进行合并数据的操作。join()函数默认是通过index来进行连接,也可以通过设置参数“on”来指定连接的列。
参数格式如下:

left.join(right,on='keys')

函数功能:将left的’keys’列和right的索引作为关键字进行比较,相同的进行合并。其等效于pandas.merge(left,right,left_on='key',right_index=True,how="left")示例代码如下:

import numpy as np
import pandas as pd
left = pd.DataFrame({'one':np.arange(4),'two':list('abcd'),
                    'key':['k0','k1','k0','k1']})
right=pd.DataFrame({'three':[4,5],'four':['e','f']},
                   index=['k0','k1'])
result=left.join(right,on='key')
print(left,'\n',right,'\n',result)
   one two key
0    0   a  k0
1    1   b  k1
2    2   c  k0
3    3   d  k1 
     three four
k0      4    e
k1      5    f 
    one two key  three four
0    0   a  k0      4    e
1    1   b  k1      5    f
2    2   c  k0      4    e
3    3   d  k1      5    f

8.2.2 沿轴连接数据

1.concat()函数
在pandas中,利用concat()函数可以沿轴将数据进行简单的连接。但concat方法不会去重,如要实现去重的效果,可以使用drop_duplicates方法。
按轴向连接数据就是单纯地将两个表拼接,这个过程也被称作连接(concatenation)、绑定(binding)或堆叠(stacking)。
concat()函数格式如下:

pandas.concat(objs,axis=0,join='outer',join_axes=None,ignore_index=False,keys=None,levels=None,names=None,names=None,verify_integrity=False,copy=True,sort=False)
参数说明如下:

  • sort: 如果True,则将合并的数据进行排序,默认为False,但在横向外连接或者ignore_index=True时要设置此参数
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-x1QweDdf-1637637711983)(concat()]参数说明.jpg)

【例】使用concat()函数,通过选择不同的参数,观察实现多个数据集的沿轴连接的效果,其示例代码如下:

import numpy as np
import pandas as pd
#定义3个Series
s1 = pd.Series([0, 1, 2], index=['a', 'b', 'c'])
s2 = pd.Series([3, 4, 5, 6], index=['d', 'e', 'f', 'g'])
s3 = pd.Series([7, 8, 9], index=['h', 'i', 'j'])
print('将s1,s2,s3纵向外连接')
result = pd.concat([s1, s2, s3])
print(result)
将s1,s2,s3纵向外连接
a    0
b    1
c    2
d    3
e    4
f    5
g    6
h    7
i    8
j    9
dtype: int64
print('将s1,s2,s3横向外连接')
result = pd.concat([s1, s2, s3], axis=1,sort=False)
print(result)

将s1,s2,s3横向外连接
     0    1    2
a  0.0  NaN  NaN
b  1.0  NaN  NaN
c  2.0  NaN  NaN
d  NaN  3.0  NaN
e  NaN  4.0  NaN
f  NaN  5.0  NaN
g  NaN  6.0  NaN
h  NaN  NaN  7.0
i  NaN  NaN  8.0
j  NaN  NaN  9.0
print('将s1*2,s3纵向外连接')
s4 = pd.concat([s1 * 2, s3])
print(s4)
print('将s1,s4横向外连接')
result = pd.concat([s1, s4], axis=1,sort=False)
print(result)
print('将s1,s4横向内连接')
result = pd.concat([s1, s4], axis=1, join='inner')
print(result)
将s1*2,s3纵向外连接
a    0
b    2
c    4
h    7
i    8
j    9
dtype: int64
将s1,s4横向外连接
     0  1
a  0.0  0
b  1.0  2
c  2.0  4
h  NaN  7
i  NaN  8
j  NaN  9
将s1,s4横向内连接
   0  1
a  0  0
b  1  2
c  2  4

print('将s1,s4横向外连接,自定义索引')
result = pd.concat([s1, s4], axis=1
)
print(result)
print('将s1,s2,s3纵向外连接,设置层次索引')
result = pd.concat([s1, s1, s3], keys=['one', 'two', 'three'])
print(result)

将s1,s4横向外连接,自定义索引
     0  1
a  0.0  0
b  1.0  2
c  2.0  4
h  NaN  7
i  NaN  8
j  NaN  9
将s1,s2,s3纵向外连接,设置层次索引
one    a    0
       b    1
       c    2
two    a    0
       b    1
       c    2
three  h    7
       i    8
       j    9
dtype: int64
print('将s1,s2,s3横向外连接,设置层次索引')
result = pd.concat([s1, s2, s3], axis=1, keys=['one', 'two', 'three'],
                   sort=False)
print(result)
将s1,s2,s3横向外连接,设置层次索引
   one  two  three
a  0.0  NaN    NaN
b  1.0  NaN    NaN
c  2.0  NaN    NaN
d  NaN  3.0    NaN
e  NaN  4.0    NaN
f  NaN  5.0    NaN
g  NaN  6.0    NaN
h  NaN  NaN    7.0
i  NaN  NaN    8.0
j  NaN  NaN    9.0
#定义一个2个DataFrame
df1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=['a', 'b', 'c'],
                columns=['one', 'two'])
df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=['a', 'c'],
                columns=['three', 'four'])
print('将df1,df2横向外连接,设置层次索引')
result = pd.concat([df1, df2], axis=1, keys=['level1', 'level2'],sort=False)
print(result)
print('使用字典设置层次索引,横向外连接')
result = pd.concat({'level1': df1, 'level2': df2}, axis=1,sort=False)
print(result)
print('将df1,df2横向外连接,设置层次索引和层次索引的级别名称')
result = pd.concat([df1, df2], axis=1, keys=['level1', 'level2'],
          names=['upper', 'lower'],sort=False)
print(result)
将df1,df2横向外连接,设置层次索引
  level1     level2     
     one two  three four
a      0   1    5.0  6.0
b      2   3    NaN  NaN
c      4   5    7.0  8.0
使用字典设置层次索引,横向外连接
  level1     level2     
     one two  three four
a      0   1    5.0  6.0
b      2   3    NaN  NaN
c      4   5    7.0  8.0
将df1,df2横向外连接,设置层次索引和层次索引的级别名称
upper level1     level2     
lower    one two  three four
a          0   1    5.0  6.0
b          2   3    NaN  NaN
c          4   5    7.0  8.0
#将两个不相同的列的数据合并
df1 = pd.DataFrame(np.random.randn(3, 4), columns=['a', 'b', 'c', 'd'])
df2 = pd.DataFrame(np.random.randn(2, 3), columns=['b', 'd', 'a'])
print('df1, df2纵向外连接,忽略原index,重建索引')
print(pd.concat([df1, df2], ignore_index=True,sort=False))

df1, df2纵向外连接,忽略原index,重建索引
          a         b         c         d
0  0.484948  2.018484 -0.023108  0.110072
1 -0.058997  0.701099  0.509739  0.151530
2 -0.831136  0.867745  0.141327 -0.815501
3 -0.917513 -2.420508       NaN -0.213645
4 -1.791165  0.064137       NaN  1.671299
2.append()函数
append()函数是concat()函数的简略形式,但是append()函数只能在axis=0上进行数据合并,函数格式如下:

left.append(right)或left.append(right,ignore_index=True)该函数的功能为:将left指定数据集与right指定数据集进行纵向合并。其中,DataFrame与Series进行合并时,需要使用参数ignore_index=True。其示例代码如下:

import numpy as np
import pandas as pd
left=pd.DataFrame({'one':np.arange(4),'two':list('abcd')})
right=pd.DataFrame({'three':[4,5],'four':['e','f']})
s1=pd.Series([0,1,2],index=['a','b','c'])
result=left.append(right,sort=False)
result1=left.append(s1,ignore_index=True)
print('左边数据:\n',left,'右边数据:\n',right,'合并数据:\n',result)
print('左边数据:\n',left,'右边数据:\n',s1,'合并数据:\n',result1)
左边数据:
    one two
0    0   a
1    1   b
2    2   c
3    3   d 右边数据:
    three four
0      4    e
1      5    f 合并数据:
    one  two  three four
0  0.0    a    NaN  NaN
1  1.0    b    NaN  NaN
2  2.0    c    NaN  NaN
3  3.0    d    NaN  NaN
0  NaN  NaN    4.0    e
1  NaN  NaN    5.0    f
左边数据:
    one two
0    0   a
1    1   b
2    2   c
3    3   d 右边数据:
 a    0
b    1
c    2
dtype: int64 合并数据:
    one  two    a    b    c
0  0.0    a  NaN  NaN  NaN
1  1.0    b  NaN  NaN  NaN
2  2.0    c  NaN  NaN  NaN
3  3.0    d  NaN  NaN  NaN
4  NaN  NaN  0.0  1.0  2.0

8.2.3合并重置数据

合并重叠数使用是combine_first()函数,该函数的语法格式:

obj1.combine_first(obj2)其中,obj1为函数调用对象的数据集,obj2为函数参数对象的数据集。该函数的作用是用函数参数对象中的数据为函数调用对象的缺失数据“打补丁”。即填充函数调用对象中的数据缺失值。

【例】示例代码如下

import numpy as np
import pandas as pd
s1=pd.Series([2,np.nan,4.2,np.nan,5.5,np.nan],index=['a','b','c','d','e','f'])
s2=pd.Series(np.arange(len(s1),dtype=np.float64),index=['a','b','c','d','e','f'])
result=s2[:-3].combine_first(s1[3:])
print(s1,'\n',s2,'\n',result)
df1=pd.DataFrame({'a':[np.nan,2.,4.,np.nan],
                 'b':[1.,np.nan,3.,np.nan],
                 'c':range(2,18,4)})
df2=pd.DataFrame({'a':[3.,np.nan,5.,7.,9.],
                 'b':[np.nan,2.,4.,6.,8.]})
result1=df1.combine_first(df2)
print(df1,'\n',df2,'\n',result)
a    2.0
b    NaN
c    4.2
d    NaN
e    5.5
f    NaN
dtype: float64 
 a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
f    5.0
dtype: float64 
 a    0.0
b    1.0
c    2.0
d    NaN
e    5.5
f    NaN
dtype: float64
     a    b   c
0  NaN  1.0   2
1  2.0  NaN   6
2  4.0  3.0  10
3  NaN  NaN  14 
      a    b
0  3.0  NaN
1  NaN  2.0
2  5.0  4.0
3  7.0  6.0
4  9.0  8.0 
 a    0.0
b    1.0
c    2.0
d    NaN
e    5.5
f    NaN
dtype: float64

8.3 数据抽取

数据抽取,也成为数据拆分,他是通过保留、抽取源数据表中的某些字段、记录的部分信息来形成一些新字段和新纪录

8.3.1 字段抽取与拆分

     字段抽取是根据已知列数据的开始和结束位置,抽取出新的列。字段抽取采用slice()函数,该函数的语法格式:
     Series.str.slice(start=None, stop=None)
     函数中的参数说明:
     start:表示字段抽取的开始位置。
     stop:表示字段抽取的结束位置。
import numpy as np
import pandas as np

#导入数据
data=pd.read_csv('p:/data/goods_sales.csv',encoding='GBK')
print(data)
    用户ID                        商品信息  数量     单价           电话
0  10001    Gree;空调;KFR-35GW/NhBaD3    1   3149  18573351234
1  10010     惠普(HP);电脑; 15-cs1013TX?   1   5569  18573354324
2  10013  联想;电脑;ThinkPad T480S(06CD)   1  16234  18810012345
3  10021   Gree;空调; KFR-72LW/NhHaD3    1   5690  18664511234
4  10023           TCL;冰箱;BCD-163KF1   1   1049  18872345636
5  10016        Haier;冰箱;BCD-118TMPA   2    999  18573323312
6  10026   Haier;洗衣机;XQB80 - KM12688   2   1399  13673327765
7  10034     Haier;洗衣机;XQB60-M12699T   4    999  13567542343
8  10027        Haier;冰箱;BCD-216WMPT   3   1999  13873325687
#将'商品信息'拆分成3列的数据框
#newData = data['商品信息'].str.split(';', 3, True)
#newData.columns = ['品牌', '分类','型号']  #设置列名
#print(newData)
#df = data.drop('商品信息', axis=1).join(newData)
#result = df.groupby(by=['品牌','数量']).agg(np.sum)
#print(result)
#result = df.groupby(by=['分类'])['数量'].agg([( '数量',np.sum)])
#print(result)
#抽取电话号码地区号
#telData = data['电话'].astype(str)
#areas = telData.str.slice(3, 7)
#print(areas)
#newDf = data.drop('电话', axis=1).join(areas)
#print(newDf)
#result = newDf.groupby(by=['电话','数量']).agg(np.sum)
#print(result)

8.3.2 记录抽取

记录抽取是指根据一定的条件,对数据进行抽取。
记录抽取函数:  datafram[condition]
其中,condition为过滤条件。函数返回值是DataFram。     
常用的条件类型
  • ① 比较运算:大于(>),小于(<),大于等于(>=),小于等于(<=),不等于(!=)。
  • ② 范围运算:between(left,right)。
  • ③ 空值匹配:pandas.isnull(column)。
  • ④字符匹配:str.contains(patten,na=False),其中na参数是指空值的处理方式,如为False,不匹配空值。
  • ⑤逻辑运算:与(&),或(|),取反(not)。

8.4重塑层次索引

     在数据处理时,有时需要对数据的结构进行重排,也称作是重塑(reshape)或者轴向旋转(pivot)。在pandas中提供了实现重塑的两个函数,即stack()函数和unstuck()函数。
     常见的数据层次化结构有两种,一种是表格,如图8-3所示,另一种是“花括号”,如图8-4所示。

在这里插入图片描述

1.stack函数

1、stack()函数
  stack()函数将数据从”表格结构“变成”花括号结构“,即将其行索引变成列索引。

2.unstack()函数

2、unstack()函数
  unstack()函数将数据从”花括号结构“变成”表格结构“,即要将其中一层的列索引变成行索引。
  • 1.stack:将数据的列“旋转”为行
  • 2.unstack:将数据的行“旋转”为列
  • 3.stack和unstack默认操作为最内层
  • 4.stack和unstack默认旋转轴的级别将会成果结果中的最低级别(最内层)
  • 5.stack和unstack为一组逆运算操作
#创建DataFrame,行索引名为state,列索引名为number
import pandas as pd
import numpy as np
data = pd.DataFrame(np.arange(6).reshape((2,3)),index=pd.Index(['Ohio','Colorado'],name='state')
                   ,columns=pd.Index(['one','two','three'],name='number'))
data

numberonetwothree
state
Ohio012
Colorado345
#将DataFrame的列旋转为行,即stack操作。
result = data.stack()
result
state     number
Ohio      one       0
          two       1
          three     2
Colorado  one       3
          two       4
          three     5
dtype: int32
#将DataFrame的行旋转为列,即unstack操作。
result.unstack()
numberonetwothree
state
Ohio012
Colorado345
#stack和unstack逆运算
s1 = pd.Series([0,1,2,3],index=list('abcd'))
s2 = pd.Series([4,5,6],index=list('cde'))
data2 = pd.concat([s1,s2],keys=['one','two'])
data2
one  a    0
     b    1
     c    2
     d    3
two  c    4
     d    5
     e    6
dtype: int64
data2.unstack().stack()
one  a    0.0
     b    1.0
     c    2.0
     d    3.0
two  c    4.0
     d    5.0
     e    6.0
dtype: float64

8.5 映射与数据转换

   映射就是创建一个映射关系列表,把元素和一个特定的标签或者字符串绑定起来。定义映射关系最好是使用字典。
   例如:map = {‘label1’:’value1’,label2’:’value2’, … }
   在pandas中提供了利用映射关系来实现某些操作的函数如下。
   replace()函数:替换元素
   map()函数:新建一列
   rename()函数:替换索引

8.5.1 用映射替换元素

1、利用replace()函数替换元素

   例如,创建字典fruits用于指明水果标识和水果名称的映射关系。
   fruits = {101:'orange',102:'apple',103:'banana'}
   如要将用于存储水果标识、水果数量和单价的DataFrame对象中的水果标识替换成水果名称,就需要运用replace()函数,通过fruits映射关系来实现元素的替换

replace()函数格式:
obj.replace(to_replace=None,Value=None,inplace=False,limit=None,regex=False,method='pad')
参数说明:

  • obj:DataFrame或Series对象
  • to_replace:接收标量、字典、列表、str、正则表达式,默认为None;用于替换与to_replace匹配的任何值的值;对于DataFrame,可以使用dict来指定每列使用哪个值(不在dict中的列将不会被填充);还允许使用正则表达式、字符串、列表或这些对象的dict
  • inplace :bool, 默认 False如果是真的,在适当的地方。注意:这将修改这个对象上的任何其他视图(例如,ataFrame中的一个列)。如果为真,则返回调用者。
  • limit : int, 默认None向前或向后填充的最大尺寸gap。
  • regex :bool或与to_replace相同的类型, 默认False,是否将to_replace和/或value解释为正则表达式。如果这是True,那么to_replace必须是一个字符串。也可以是正则表达式或正则表达式的列表、dict或数组,在这种情况下to_replace必须为None。
  • method :{‘pad’, ‘ffill’, ‘bfill’, None}用于替换时,当to_replace是标量时,列表或元组,值为None时使用的方法。
#【例】利用replace函数和映射关系实现将水果数据框中水果表示替换成水果名称
import numpy as np
import pandas as pd
#创建水果标识与水果名称的映射关系
fruits = {101:'orange',102:'apple',103:'banana'}
#创建水果数据框DataFrame
data = pd.DataFrame({'fru_No':[101,102,103],'fru_Num':[1000,2000,3000]
                        ,'price':[3.56,4.2,2.5]})
#用映射替换'fru_No'列的元素
newDf = data.replace(fruits)
print(newDf)
   fru_No  fru_Num  price
0  orange     1000   3.56
1   apple     2000   4.20
2  banana     3000   2.50

【例】replace函数应用

import numpy as np
import pandas as pd
from pandas import Series,DataFrame

s = Series([-1000,-999,2,3,4,5,-2000])
#单数值替换
print(s.replace(-2000,np.nan))
0   -1000.0
1    -999.0
2       2.0
3       3.0
4       4.0
5       5.0
6       NaN
dtype: float64
#将多个数值替换
print(s.replace([-1000,-999],0))
0       0
1       0
2       2
3       3
4       4
5       5
6   -2000
dtype: int64
#不同的值进行不同的替换
print(s.replace([-1000,-999],[np.nan,0]))
0       NaN
1       0.0
2       2.0
3       3.0
4       4.0
5       5.0
6   -2000.0
dtype: float64
#用字典方式进行不同的替换
print(s.replace({-1000:np.nan,-999:0,-2000:np.nan}))
0    NaN
1    0.0
2    2.0
3    3.0
4    4.0
5    5.0
6    NaN
dtype: float64

8.5.2 用映射添加元素

在上面的例题中中介绍了利用函数和映射来实现将水果标识替换成水果名称的方法。但是有时需要保留水果标识,将水果名称添加到数据集中。那么,这时可利用map()函数,通过构建fruits映射关系来实现元素的添加。

map()函数是作用于Series或DataFrame对象的一列,它接收一个函数或表示映射关系的字典作为参数,格式如下:
Series.map(arg,na_action=None)

参数说明:

  • arg:结合搜function、dict、Series,表示映射通信
  • na_action:取值为{无,‘忽略’},默认值为None,如果为“忽略”,则传播NA值,而不是将他们传递给映射关系

【例】利用map()函数和映射关系实现将水果名称添加到水果数据框中

import pandas as pd
# 创建水果标识与水果名称的映射关系
fruits={101:'orange',102:'apple',103:'banana'}
#创建水果数据框DataFrame
data=pd.DataFrame({'fru_No':[101,102,103],'fru_Num':[1000,2000,3000],
                   'price':[3.56,4.2,2.5]})
#用映射为data添加fru_name元素
data['fru_name']=data['fru_No'].map(fruits)
print(data)
   fru_No  fru_Num  price fru_name
0     101     1000   3.56   orange
1     102     2000   4.20    apple
2     103     3000   2.50   banana

8.5.3 重命名索引

在数据处理中,有时需要使用映射关系转换轴标签。pandas的rename()函数,是以表示映射关系的字典对象作为参数,替换轴的索引标签。
rename()函数的基本语法格式:

DataFrame.rename(mapper=None,index=None,columns=None,axis=None,copy=True,inplace=False,level=None)或Series.rename(index=None,**kwargs)

参数说明:

  • mapper,index,columns: 接收dict或function,表示将dict或函数转换为应用于该轴的值,使用mapper参数要指定映射器;使用columns参数可重命名各列
  • axis:接收int或str,可选,表示映射器定位的轴,可以使轴名称(“index”,“columns”)或数字(0,1
    ),默认为“index”。
  • copy:接收boolean。默认为True,表示是否复制数据
  • inplace:接收boolean,默认为False,如果为True,将会修改原来的数据
  • level:接收int或level name,默认为None,如果是MultiIndex,只重命名指定级别中的标签
    rename()函数返回值是DataFrame或Series

【例】利用rename()函数和映射关系重命名水果数据框的行索引和列索引

import pandas as pd
#创建行索引的映射关系
reindex={0:'row1',1:'row2',2:'row3'}
#创建水果数据框DataFrame
data = pd.DataFrame({'fru_No':[101,102,103],'fru_Num':[1000,2000,3000]\
                        ,'price':[3.56,4.2,2.5]})
#用映射重命名水果数据框的行索引,产生新DataFrame,但原数据不改变
newDf = data.rename(reindex)
print(newDf,'\n',data)
      fru_No  fru_Num  price
row1     101     1000   3.56
row2     102     2000   4.20
row3     103     3000   2.50 
    fru_No  fru_Num  price
0     101     1000   3.56
1     102     2000   4.20
2     103     3000   2.50
#用映射重命名水果数据框的行索引,产生新DataFrame,但原数据改变
newDf = data.rename(reindex,inplace=True)
print(newDf,'\n',data)
None 
       fru_No  fru_Num  price
row1     101     1000   3.56
row2     102     2000   4.20
row3     103     3000   2.50
#创建列索引的映射关系
recolumns = {'fru_No':'col1','fru_Num':'col2','price':'col3'}
#用映射重命名水果数据框的行索引和列索引
newDf = data.rename(index=reindex,columns=recolumns)
print(newDf)
      col1  col2  col3
row1   101  1000  3.56
row2   102  2000  4.20
row3   103  3000  2.50
#用映射重命名水果数据框的单个行索引和单个列索引
newDf = data.rename(index={0:'row1'},columns={'fru_No':'col1'})
print(newDf)

      col1  fru_Num  price
row1   101     1000   3.56
row2   102     2000   4.20
row3   103     3000   2.50

用rename()函数返回一个经过改动的新的DataFrame对象,但原DataFrame对象仍然保持不变,如果要改变调用函数的对象本身,可使用inplace选项,并将其值设置为True

8.6排列和随机抽样

1. 排列

利用numpy.random.permutation()函数,可以返回一个序列的随机排列。将此随机排列作为take()函数的参数,通过应用take()函数就可实现按此随机排列来调整Series对象或DataFrame对象各行的顺序。
import numpy as np
import pandas as pd

#创建DataFrame
df = pd.DataFrame(np.arange(12).reshape(4,3))
print(df)
#创建随机排列
order = np.random.permutation(4)
#通过随机排列调整DataFrame各行顺序
newDf = df.take(order)
print(newDf)
   0   1   2
0  0   1   2
1  3   4   5
2  6   7   8
3  9  10  11
   0   1   2
3  9  10  11
2  6   7   8
1  3   4   5
0  0   1   2

2.随机采样

随机抽样是指随机从数据中按照一定的行数或者比例抽取数据。随机抽样的函数:

numpy.random.randint(start,end,size)

import numpy as np
import pandas as pd

#创建DataFrame
df = pd.DataFrame(np.arange(12).reshape(4,3))
print(df)
#随机抽样
order = np.random.randint(0,len(df),size=3)
#通过随机抽样抽取DataFrame中的行
newDf = df.take(order)
print(newDf)
   0   1   2
0  0   1   2
1  3   4   5
2  6   7   8
3  9  10  11
   0   1   2
0  0   1   2
3  9  10  11
3  9  10  11

8.7 日期转换、日期格式化和日期抽取

1.日期转换

日期转换是指将字符型的日期格式的数据转换成为日期型数据的过程。日期转换函数to_datetime()的语法格式:

pandas.to_datetime(dateString,format)

函数中的参数说明:

dateString:表示字符型时间列。

在这里插入图片描述
在这里插入图片描述

2、日期格式化

日期格式化是将时间日期型数据,按照指定格式,转为字符型数据。日期格式化函数:
df_dt.dt.strftime(format)```

函数中的参数说明:

df_dt:表示数据框中时间列名。

format:表示时间日期格式

### 3、日期抽取
   日期抽取是指从日期格式里面抽取出需要的部分属性。
   抽取语法:
```df_dt.dt.property```

参数说明:

df_dt:表示数据框中时间列名。 

property:表示时间属性
![](时间属性.jpg)

# <!!!> 实例**见时间日期转换实例**

## 8.8字符串处理
### 8.8.1内置的字符串的处理方法
#### 1.字符串拆分
    split()函数的作用是通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则仅分隔 num 个子字符串,其语法格式:
```str.split(str="", num=string.count(str))```

参数说明:
- str:表示字符串的分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
- num:表示分割次数。
- 函数返回值:分割后的字符串列表。


```python
str4='#this is string example##'
print(str4)
#this is string example##
print(str4.split(' '))
['#this', 'is', 'string', 'example##']
print(str4.split(' ',str.count(' ')))
['#this', 'is', 'string', 'example##']
print(str4.split(' ',2))
['#this', 'is', 'string example##']
2.一处字符串头尾指定字符
strip()函数可用于移除字符串头尾指定的字符(默认为空格)。

str.strip(chars)
该函数中参数chars表示移除字符串头尾指定的字符

函数返回值为移除字符串头尾指定的字符生成的新字符串

stra1='#this is string example##'
print(stra1.strip('#'))
this is string example
3.字符串连接
      join()函数可以将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串。

'sep'.join(seq)

参数说明:

sep:表示字符串的分隔符,可以为空
seq:表示要连接的元素序列、字符串、元组、字典

函数返回值为一个以分割符sep连接各个元素后生成的字符串。除了jion()函数外,还可以用“+”号将多个字符串连接起来

arr=['a','b','c']
stra2=arr[0]+':'+arr[1]+':'+arr[2]
print(stra2)
str1=':'
str2=arr
print(str1.join(str2))
a:b:c
a:b:c
4、判断是否是子字符串
判断是否是子字符串可以使用in关键字,或者使用find()函数和index()函数判断一个子字符串的位置。
find()函数作用是查找子字符串,若找到返回从0开始的下标值,若找不到返回-1。find()函数返回值是返回子字符串第一次出现的位置的下标值。

格式:str.find(chars)

index()函数作用是在字符串里查找子串第一次出现的位置,类似字符串的find方法,如果查找不到子串,会抛出异常。

格式:str.index(chars)

chars表示要查找的子字符串
函数返回值为返回字符串第一次出现的位置的下标值
stra='#this is string example##'
print(stra.find('s'))
print(stra.index('s'))
4
4
if 's' in stra:
    print(stra.find('s'))
4
print(stra.find('o'))
-1
print(stra.index('a'))
18
5、判断子字符串出现的次数
count()函数可用于统计字符串里某个字符出现的次数,函数的可选参数为字符串搜索的开始与结束位置。函数返回值:返回子字符串在字符串中出现的次数。

格式:str.count(sub,start,end)

参数说明:
sub:表示搜索的子字符串
start:表示字符串开始搜索的位置,默认为第一个字符,第一个字符索引值为0
end:表示字符串中结束搜索的位置,默认字符串的最后一个位置
函数返回值为返回子字符串在字符串中出现的次数
strb='#this is string example##'
print(strb.count('s'))
print(strb.count('s',0,5))
print(strb.count('s',5,len(str)))
3
1
2
6、替换子字符串
     replace()函数可将字符串中的old(旧字符串)替换成new(新字符串),如果指定第三个参数max,则替换不超过max次。
或str.count(sub,start=0,end=len(string))```

     old:表示被替换的字符串
     new:表示新字符串,用于替换old子字符串
     max:可选项,表示替换不超过max次
     函数返回值为返回字符串中的old替换成new后生成的新字符串,如果指定第三个参数max,则替换不超过max次


```python
strc = "新浪网www.sina.com"
print (strc.replace('com','cn.com'))

strd = "#this is string example##"
str1 = strd.replace('is', 'was')
str2 = str1.replace('#','!',2)
print(str1,'\n',str2)

新浪网www.sina.cn.com
#thwas was string example## 
 !thwas was string example!#

8.8.2正则表达式

正则表达式是一个特殊的字符序列,使用正则表达能很方便地在文中查找和匹配字符串模式。Python自1.5版本起增加了re模块,re模块使Python语言拥有全部的正则表达式功能。
单条正则表达式通常被称作regex,它是根据正则表达式语言编写的字符串。Python内置的re模块用于操作regex对象。只有使用import re语句,先导入re模块,才能使用正则表达式。
 re模块所提供的函数分为三类:模式匹配、替换和拆分。
1、compile()函数
compile()函数用于编译正则表达式,生成一个正则表达式(Pattern)对象,供match()和search()这两个函数使用。

格式:re.compile(pattern[,flags])

参数说明:
pattern:表示一个字符串形式的正则表达式
flags:可选,表示匹配模式,如忽略大小写、多行模式等,具体参数见表《正则表达式修饰符-标志(flass)参数》
re.compile()函数返回值为RegexObject对象
2、正则表达式对象
正则表达式对象也称为RegexObject对象。
(1)正则表达式修饰符
 正则表达式修饰符—标志(flags)参数见下表

在这里插入图片描述

 (2)正则表达式模式
     正则表达式模式是使用特殊的语法来表示一个正则表达式,它的规则:
·正则表达式模式中的字母和数字匹配相同的字符串。
·多数字母和数字前加一个反斜杠时会拥有不同的含义。
·标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。
·反斜杠本身需要使用反斜杠转义。
由于正则表达式通常都包含反斜杠,如模式元素r'\t',等价于 '\\t'。因此,正则表达式中一般都使用r'..'(raw字符串)来定义规则字符串。。
正则表达式模式语法中的特殊元素见下表:

在这里插入图片描述
在这里插入图片描述

3、re.match()函数
re.match()函数尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

re.match(parrern,string,flags=0)

参数说明:
pattern:表示要匹配的正则表达式
string:表示要匹配的字符串
flags:标志位。用于控制正则表达式的匹配方式(例如:区分大小写,多行匹配等,具体见上表)
函数返回值为match()函数从字符串开头开始匹配,匹配成功re.match()函数返回任何一个匹配的对象。如果第一个字符就不匹配,他不会再搜索字符串内部。如果没能找到任何匹配的子字符串,将返回None
match()函数可以使用group(num)或groups()匹配对象函数来获取匹配表达式
import re
print(re.match(r'(w*)', 'WWW.baidu.com',re.I).span())  # 在起始位置匹配
print(re.match(r'[com]', 'www.baidu.com'))
(0, 3)
None
str = "#This is String example##"
pattern = re.compile(r'(.*) is (.*)')
m_Obj = re.match(pattern, str)

if m_Obj:
    print('m_Obj.group():', m_Obj.group())
    print('m_Obj.group(1):', m_Obj.group(1))
    print('m_Obj.group(2):', m_Obj.group(2))
else:
    print('No match!!')
m_Obj.group(): #This is String example##
m_Obj.group(1): #This
m_Obj.group(2): String example##
str1 = "WWW.sina.com,www.163.com"
pattern = re.compile(r'(\D*\d*)')
m_Obj = re.match(pattern, str1)
print('m_Obj.group():', m_Obj.group())
m_Obj.group(): WWW.sina.com,www.163
4、 re.search()函数
re.search()函数扫描整个字符串并返回第一个成功的匹配。
注意:re.match()函数只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search()函数匹配整个字符串,直到找到一个匹配

格式:re.reach(pattern,string,flags=0)

函数返回值为匹配成功re.search()函数返回一个匹配的对象,否则返回None
import re
print(re.search(r'(w*)', 'www.baidu.com').span(),re.M|re.I)  # 在起始位置匹配
print(re.search(r'[com]', 'www.baidu.com').span())   # 不在起始位置匹配

(0, 3) re.IGNORECASE|re.MULTILINE
(10, 11)
str1 = "www.163.com,www.51job.com"
pattern = re.compile(r'\d{3}|\d{2}')
m_Obj = re.search(pattern, str1)
print('m_Obj.group():', m_Obj.group())

m_Obj.group(): 163

注意:re.match()函数只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search()函数匹配整个字符串,直到找到一个匹配

5.检索与替换
re模块提供了re.sub()函数用于替换字符串中的匹配项。

re.sub(pattern,repl,string,count=0,flages=0)

函数说明:
pattern:表示正则表达式中的字符串
repl:表示替换的字符串,也可为一个函数
string:表示要被查找/替换的原始字符串
count:表示匹配后替换的最大次数,默认为0,替换所有
import re
str6="#This is String example##"
#删除字符串中的前后#号
sub_str = re.sub(r'^#*|#*$', '', str6)
print(sub_str)
This is String example
#将字符串中的空格替换成“-"
new_sub_str = re.sub(' ', '-', sub_str)
print(new_sub_str)
This-is-String-example
# 删除tel字符串中圆括号
tel = '(0731)22768450'
num = re.sub(r'\D', '', tel)
print('电话号码是:', num)

电话号码是: 073122768450
6、findall()函数
findall()函数可在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

pattern.findall(string[,pos[,endpos]])

参数说明:
string:表示待匹配字符串
pos:可选参数,表示指定字符串的起始位置,默认为0
endpos:可选参数,表示指定字符串的结束位置,默认字符串的长度

match()函数和search()函数只匹配一次,findall()函数匹配所有项

import re
pattern = re.compile(r'\d+')
num1 = pattern.findall('www.163.com,www.51job.com')
print(num1)
['163', '51']
num2 = pattern.findall('www.163.com,www.51job.com',0,7)
print(num2)
['163']
7、re.finditer()函数
finditer()函数与findall()函数类似,可在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

re.finditer(pattern,string,flags=0)

import re
#查找字符串的数字,返回一个迭代器
num=re.finditer(r'\d+','adhadwg252agywfdqwdqj10w')
for i in num:
    print (i.group())
252
10
8、re.split()函数
split()函数按照能够匹配的子串将字符串分割后返回列表。

re.split(pattern,string[,maxsplit=0,flags=0])

参数说明:
maxsplit:表示分隔次数,maxsplit=1分隔一次,默认为0,不限制次数  
import re
#删除str字符串中的空格
str = "This is String example"
str_list = str.split(' ')
new_str_list = ''.join(str_list)
print(new_str_list)
ThisisStringexample
#将str字符串按空格拆分成列表
str_list = re.split(' ', str)
print(str_list)

['This', 'is', 'String', 'example']

8.8.3 矢量化的字符串函数

1、cat()字符串连接
cat()函数可实现元素级的字符串连接操作,并可指定分隔符。

格式:Series.str.cat(others=None,sep=None,na_rep=None)

参数说明:
others:表示Series、index、DataFrame、np.ndarry(一维或二维)和其他类似字符串的列表
sep:表示连接分隔符,取值string或None,默认为None
na_rep:当na_rep为None,序列中的NaN值将被忽略,如果指定,将用该字符串替代

2、split()切分字符串
split()函数可根据分隔符或正则表达式对字符串进行拆分。

格式:Series.str.split(pat=None,n=-1,expand=False)

参数说明:
pat:表示要拆分的字符串或正则表达式,如果未指定,则拆分空格
n:表示限制输出中的分割数,无、0和-1将被解释为返回所有拆分
expand:将拆分的字符串展开为单独的列,如果为True,则返回DataFrame/MultiIndex扩展维度;如果为False,则返回包含字符串列表的Series/Index
3. get()获取指定位置的字符串
get()函数可获取各元素的第i个字符。

格式:Series.str.get(i)

import numpy as np
import pandas as pd
#1 cat()
s = pd.Series(['a', 'b', np.nan, 'd'])
print(s.str.cat(['A', 'B', 'C', 'D'], sep=','))
print(s.str.cat(['A', 'B', 'C', 'D'], sep=',', na_rep='-'))
0    a,A
1    b,B
2    NaN
3    d,D
dtype: object
0    a,A
1    b,B
2    -,C
3    d,D
dtype: object
#2 split()
s = pd.Series(["this is good text", "but this is even better"])
print(s.str.split("is", n=1, expand=True))
        0                1
0      th     is good text
1  but th   is even better
#3 get()
s = pd.Series(["String",
           (1, 2, 3),
           ["a", "b", "c"],
           123, -456,
           {1:"Hello", "2":"World"}])
print(s.str.get(1))
0        t
1        2
2        b
3      NaN
4      NaN
5    Hello
dtype: object

除了cat()、split()和get()函数外,Series类的str自带的其它函数,即矢量化的字符串函数见表8-6,其函数语法格式是Series.str.函数名(参数)。
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TryBest_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值