序列与数据框的构造外部数据的读取(文本文件读取、电子表格读取、数据库数据读取)数据类型转换及描述统计字符与日期数据的处理数据清洗方法(重复观测处理、缺失值处理、异常值处理)数据子集的获取透视表表之间的合并与连接分组聚合
目录
一、序列与数据框的构造
1.1构造序列
1.2构造数据框
二、外部数据的读取
2.1文本文件的读取
2.2电子表格的读取
三、数据类型转换及描述统计
四、字符与日期数据的处理
一、序列与数据框的构造
Pandas模块的核心操作对象就是序列(series)和数据框(DataFrame)。序列可以理解为数据集中的一个字段,数据库是指含有至少两个字段(或序列)的数据集。
1.1构造序列
构造序列的方式:
通过同质的列表或元组构建通过字典构建通过Numpy中的一维数组构建通过数据框DataFrame中的某一列构建
#导入模块import pandas as pdimport numpy as np#构造序列gdp1=pd.Series([2.8,3.01,8.99,8.59,5.18])gdp2=pd.Series({'北京':2.8,'上海':3.01,'江苏':8.59})gdp3 = pd.Series(np.array((2.8,3.01,8.99,8.59,5.18)))print(gdp1)print(gdp2)print(gdp3)out:0 2.801 3.012 8.993 8.594 5.18dtype: float64北京 2.80上海 3.01江苏 8.59dtype: float640 2.801 3.012 8.993 8.594 5.18dtype: float64
Series构造的序列结果会产生两列,第一列属于序列的行索引(可以理解为行号),自动从0开始,第二例是序列的实际的值。通过字典构造,第一列是行名称,对应字典的键,第二列是序列的实际值,对应字典的值。
序列与一维数组有极高相似性,获取一维数组的索引方法可以应用在序列上,而且数组的数学和统计函数也可以用在序列对象上,不过序列有更多的其他处理方法
# 数学函数--取对数print('通过numpy函数:\n',np.log(gdp1))# 平均gdpprint('通过numpy函数:\n',np.mean(gdp1))print('通过序列的方法:\n',gdp1.mean())out:通过numpy函数:0 1.0296191 1.1019402 2.1961133 2.1505994 1.644805dtype: float64通过numpy函数:5.714通过序列的方法:5.714
1.2构造数据框
数据框实质就是一个数据集,数据集的行代表每一条观测,数据集的列代表各个变量。在一个数据框中可以存放不同数据类型的序列,如整数型、浮点型、字符型和日期时间型,而数组和序列没有这样的优势,因为他们只能存放同质数据。构造一个数据库应用如下方式:
通过嵌套的列表或元组构造通过字典构造通过二维数组构造通过外部数据的读取构造
# 构造数据框df1 = pd.DataFrame([['张三',23,'男'],['李四',27,'女'],['王二',26,'女']])df2 = pd.DataFrame({'姓名':['张三','李四','王二'],'年龄':[23,27,26],'性别':['男','女','女']})df3 = pd.DataFrame(np.array([['张三',23,'男'],['李四',27,'女'],['王二',26,'女']]))print('嵌套列表构造数据框:\n',df1)print('字典构造数据框:\n',df2)print('二维数组构造数据框:\n',df3)out:嵌套列表构造数据框:0 1 20 张三 23 男1 李四 27 女2 王二 26 女字典构造数据框:姓名 年龄 性别0 张三 23 男1 李四 27 女2 王二 26 女二维数组构造数据框:0 1 20 张三 23 男1 李四 27 女2 王二 26 女
构造数据框需要使用pandas模块中的DataFrame。将嵌套列表、元组或二维数组转换为数据框是,数据框无具体变量名,只有从0到n的列号。所以,如果需要手工构造数据框时,一般首选字典方法。
二、外部数据的读取
2.1文本文件的读取
如果读取txt或csv格式的数据,可以使用pandas模块中的read_table函数或者read_csv函数。这两个函数均可以读取文本文件的数据。
pd.read_table(filepath_or_buffer,sep='t',header='infer',names=None,index_col=None,usecols=None,dtype=None,converters=None,skiprows=None,skipfooter=None,nrows=None,na_values=None,skip_blank_lines=True,parse_dates=False,thousands=None,comment=None,encoding=None)
filepath_or_buffer,指定文件路径;
sep,分隔符、默认Tab制表符;
header,是否第一行做表头,默认是;
names,原数据集中无字段,可以通过该参数在数据读取时给数据框添加具体的表头;
index_col,指定原数据集中的某些列作为数据框的行索引(标签);
usecols,指定需要读取数据集中的哪些变量名;
dtype,读取数据时,可以为原数据集的每个字段设置不同的数据类型
converters,通过字典格式,为数据集中的某些字段设置转换函数
skiprows,数据读取时,指定需要跳过原数据集开头的行数
skipfooter,数据读取时,指定需要跳过原数据集末尾的行数
nrows,指定读取数据的行数
na_values,指定哪些特征的值为缺失值
skip_blank_lines=True,读取数据时是否需要跳过原数据集中的空白行,默认True
parse_dates=False,如果参数值为True,则尝试解析数据框的行索引;如果参数值为列表,则分析对应的日期列;如果参数值为嵌套列表,则将某些列合并为日期列;如果参数为字典,则对应列(字典中的值),并生成新的字段名(字典中的键)
thousands=None,指定原始数据集的千分位符;
comment=None,指定注释符,在读取数据时,如果碰到行首指定的注释符,则跳过该行
encoding=None如果文件中含有中文,有时候需要指定字符编码
# 读取文本文件中的数据user_income = pd.read_table(r'''C:\Users\yu'chuan'zhao\Desktop\pythondatacourse\第5章 Python数据处理工具--Pandas\data_test01.txt''', sep = ',', parse_dates={'birthday':[0,1,2]},skiprows=2, skipfooter=3, comment='#', encoding='utf8', thousands='&')user_incomeout:birthday gender occupation income0 1990-03-07男 销售经理 60001 1989-08-10女 化妆师 85002 1992-10-07女 前端设计 65003 1985-06-15男数据分析师 18000
2.2电子表格的读取
运用read_execl函数,读取电子表格数据。
pd.read_excel(io,sheetname=0,header=0,skip_footer=0,index_col=None,names=None,parse_cols=None,parse_dates=False,na_values=None,thousands=None,convert_float=True)
io,电子表格具体路径
sheetname=0,指定需要读取电子表格中的第几个sheet,既可以传递整数
header=0,是否需要将数据集的第一行用做表头,默认为是需要的
skip_footer=0,读取数据时,指定跳过的开始行数
index_col=None,指定哪些列用作数据框的行索引
names=None,如果原数据集中没有字段,可以通过该参数在数据读取时给数据框添加具体的表头
parse_cols=None,指定需要解析的字段
parse_dates=False,如果参数值为True,则尝试解析数据框的行索引;如果参数值为列表,则分析对应的日期列;如果参数值为嵌套列表,则将某些列合并为日期列;如果参数为字典,则对应列(字典中的值),并生成新的字段名(字典中的键
na_values=None,指定原始数据集中的千分位符
thousands=None,指定原始数据集中的千分位符
convert_float=True 默认将所有的数值型字段转换为浮点型字段
converters通过字典的形式,指定某些列需要转换的形式。
child_cloth = pd.read_excel(io = r'''C:\Users\yu'chuan'zhao\Desktop\pythondatacourse\第5章 Python数据处理工具--Pandas\data_test02.xlsx''', header = None, names = ['Prod_Id','Prod_Name','Prod_Color','Prod_Price'], converters = {0:str})child_clothout: Prod_Id Prod_Name Prod_Color Prod_Price0 00101 儿童裤 黑色 1091 01123儿童上衣 红色 2292 01010 儿童鞋 蓝色 1993 00100儿童内衣 灰色 159
重点说明converters参数,通过该参数可以指定某些变量需要转换的函数。很显然,原始数据集中的商品ID是字符型的,如果不将该参数设置为{0:str},读入的数据与原始的数据集就不一致了。
三、数据类型转换及描述统计
在我们读取了数据之后,如何了解数据,比如数据的规模、变量所属的数据类型,一些重要指标等,如何查找
#数据读取sec_cars=pd.read_table(r'''C:\Users\yu'chuan'zhao\Desktop\pythondatacourse\第5章 Python数据处理工具--Pandas\sec_cars.csv''',sep=',')#预览数据的前五行sec_cars.head()out:Brand Name ... Sec_price New_price0 众泰 众泰T600 款 1.5T 手动 豪华型 ... 6.89.42万1 众泰 众泰Z700 款 1.8T 手动 典雅型 ... 8.811.92万2 众泰大迈X5 款 1.5T 手动 豪华型 ... 5.88.56万3 众泰 众泰T600 款 1.5T 手动 精英贺岁版 ... 6.28.66万4 众泰 众泰T600 款 1.5T 手动 旗舰型 ... 7.011.59万
如果只需要预览数据的几行信息,可以使用head方法和tail方法。数据集前五行head,数据集后五行tail。
如果还想知道数据集中有多少观测和多少变量,以及每个变量都是什么类型,可由如下代码得知:
#查看数据的行列数print('数据集的行列数: \n',sec_cars.shape)#查看数据集的每个变量的数据类型print('各变量的数据类型:\n',sec_cars.dtypes)out:数据集的行列数: (10984, 7)各变量的数据类型:Brand objectName objectBoarding_timeobjectKm(W) float64Discharge objectSec_price float64New_price objectdtype: object
Boarding_time应该为日期型,新车价格New_price 应该为浮点型,为了后面的数据分析,需要对这两个变量进行类型的转换,具体操作如下:
# 修改二手车上牌时间的数据类型sec_cars.Boarding_time = pd.to_datetime(sec_cars.Boarding_time, format = '%Y年%m月')# 修改二手车新车价格的数据类型sec_cars.New_price = sec_cars.New_price.str[:-1].astype('float')# 重新查看各变量数据类型sec_cars.dtypesout:BrandobjectName objectBoarding_time datetime64[ns]Km(W) float64DischargeobjectSec_pricefloat64New_pricefloat64dtype: object
pandas模块中的to_datetime函数可以通过format参数灵活地将各种格式的字符型日期转换成真正的日期数据;由于二手新车价格含有“万”字,因此不能直接转换数据类型,为达到目的,首先字段转换成字符串,然后切片将“万”字剔除,最后运用astype方法,实现数据类型的转换。
需要对数据做到心中有数,通过基本的统计量(最小值、均值、中位数、最大值等)描述出数据的特征。数据的描述性分析可以使用describe方法。
#数据的描述性统计sec_cars.describe()Out: Km(W)Sec_priceNew_pricecount 10984.000000 10984.000000 10984.000000mean 6.26635725.65219251.326006std 3.48067852.77026879.682066min 0.0200000.6500002.91000025% 4.0000005.20000016.05000050% 6.00000010.20000026.69000075% 8.20000023.80000052.210000max 34.600000 808.000000 976.920000
一次性统计数值型变量的偏度和峰度
# 数据的形状特征# 挑出所有数值型变量num_variables = sec_cars.columns[sec_cars.dtypes !='object'][1:]# 自定义函数,计算偏度和峰度def skew_kurt(x):skewness = x.skew()kurtsis = x.kurt()# 返回偏度值和峰度值return pd.Series([skewness,kurtsis], index = ['Skew','Kurt'])# 运用apply方法sec_cars[num_variables].apply(func = skew_kurt, axis = 0)out:Km(W) Sec_price New_priceSkew 0.829915 6.313738 4.996912Kurt 2.406258 55.381915 33.519911
对离散型变量的统计描述仍然可以使用describe方法,所不同的是,需要设置该方法的include参数,具体如下
# 离散型变量的统计描述sec_cars.describe(include = ['object'])
四个统计值分别是 非缺失观测数、唯一水平数、频次最高的离散值和具体的频次。
四、字符与日期数据的处理
以下图为例,完成字符串和日期数据的处理
如何更改birthday和tel两个字段的数据类型如何根据birthday和start_work两个字段新增年龄和工龄两个字段如何将tel中间四位隐藏起来如何根据邮箱信息新增邮箱域名字段如何基于other字段取出每个人员的专业信息
# 数据读入df = pd.read_excel(r'C:\Users\Administrator\Desktop\data_test03.xlsx')# 各变量数据类型print(df.dtypes)# 将birthday变量转换为日期型df.birthday = pd.to_datetime(df.birthday, format = '%Y/%m/%d')# 将手机号转换为字符串df.tel = df.tel.astype('str')# 新增年龄和工龄两列df['age'] = pd.datetime.today().year - df.birthday.dt.yeardf['workage'] = pd.datetime.today().year - df.start_work.dt.year# 将手机号中间四位隐藏起来df.tel = df.tel.apply(func = lambda x : x.replace(x[3:7], '****'))# 取出邮箱的域名df['email_domain'] = df.email.apply(func = lambda x : x.split('@')[1])# 取出用户的专业信息df['profession'] = df.other.str.findall('专业:(.*?),')# 去除birthday、start_work和other变量df.drop(['birthday','start_work','other'], axis = 1, inplace = True)df.head()out:name gender incometel ... age workage email_domain profession0 赵一男 15000 136****1234 ... 33 10 [电子商务]1 王二男 12500 135****2234 ... 32 8 [汽修]2 张三女 18500 135****3330 ... 35 13[数学]3 李四女 13000 139****3388 ... 31 8 [统计学]4 刘五女 8500 178****7890 ... 30 8[美术]
pandas模块中的to_datetime函数将birthday转换为日期型(必须按照原始的birthday格式设置format参数);使用astype方法将tel转换为字符型。
在使用year方法之前,需要使用dt方法,否则会出错。
# 常用日期处理方法dates = pd.to_datetime(pd.Series(['1989-8-18 13:14:55','1995-2-16']), format = '%Y-%m-%d %H:%M:%S')print('返回日期值:\n',dates.dt.date)print('返回季度:\n',dates.dt.quarter)print('返回几点钟:\n',dates.dt.hour)print('返回年中的天:\n',dates.dt.dayofyear)print('返回年中的周:\n',dates.dt.weekofyear)print('返回星期几的名称:\n',dates.dt.day_name)print('返回月份的天数:\n',dates.dt.days_in_month)