社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

python数据处理工具--Pandas模块

奈何缘浅wyj • 4 年前 • 442 次点击  
阅读 5

python数据处理工具--Pandas模块

强大的数据处理模块Pandas,可以解决数据的预处理工作,如数据类型的转换、缺失值的处理、描述性统计分析和数据的汇总等

一、序列与数据框的构造

Pandas模块的核心操作对象为序列和数据框。序列指数据集中的一个字段,数据框为至少含有两个字段(或序列)的数据集。

1.构造序列

image

image

通过列表、元祖、Numpy中的一维数组构造序列均如序列1,第一列为序列的行索引(行号),自动从0开始;第二列为序列的实际值

通过字典构造不同,第一列为具体的行名称,对应字典中的键,第二列为序列的实际值,对应字典中的值。

还可以通过数据框中的某一列构建

2.序列元素的获取

对一维数组的索引方法和数学以及统计函数都可以用到序列上,但序列有特有的处理方法。

image

image

对通过字典类型构建的,可用行号,也可用行名称索引

image

如果需要对序列做数学函数计算,首选numpy模块

image

如果需要对序列做统计函数计算,首选序列的方法

3.构造数据框

数据框实际是一个数据集,行代表每一条观测,列代表各个变量。在一个数据库中可以存放不同数据类型的序列,而数组和序列只能存放同质数据。

image

手工构造数据框的话,首选字典方法,因为其他方法构造没有具体的变量名

还可以通过外部数据的读取构造

二、外部数据的读取

1.文本文件的读取

使用Pandas中的read_table函数或者read_csv函数

image

filepath_or_buffer:指定txt文件或csv文件所在的具体路径; sep:指定原数据集中各字段之间的分隔符,默认为Tab制表符; header:是否需要将原数据集中的第一行作为表头,默认将第一行用作字段名称; names:如果原数据集中没有字段,可以通过该参数在数据读取时给数据框添加具体的表头; index_col:指定原数据集中的某些列作为数据框的行索引(标签); usecols:指定需要读取原数据集中的哪些变量名; dtype:读取数据时,可以为原数据集的每个字段设置不同的数据类型; converters:通过字典格式,为数据集中的某些字段设置转换函数 skiprows:数据读取时,指定需要跳过原数据集开头的行数; skipfooter:数据读取时,指定需要跳过原数据集末尾的行数; nrows:指定读取数据的行数; na_values:指定原数据集中哪些特征的值作为缺失值; skip_blank_lines:读取数据时是否需要跳过原数据集中的空白行,默认为True; parse_dates:如果参数值为True,则尝试解析数据框的行索引;如果参数为列表,则尝试解析对应的日期列;如果参数为嵌套列表,则将某些列合并为日期列;如果参数为字典,则解析对应的列(即字典中的值),并生成新的字段名(即字典中的键); thousands:指定原始数据集中的千分位符; comment:指定注释符,在读取数据时,如果碰到行首指定的注释符,则跳过改行; encoding:如果文件中含有中文,有时需要指定字符编码;

image

a=pd.read_table("F:\第5章 Python数据处理工具--Pandas\第五章 Python数据处理工具--Pandas\data_test01.txt",sep=",",skiprows=2,skipfooter=3,comment="#",encoding="utf8",thousands="&",parse_dates={"birthday":[0,1,2]})
a

复制代码

image

原数据集用逗号分隔每一列,则改变sep参数,合并新字段birthday,comment参数指定跳过的特殊行,含有中文的重新编码,千分位符为了保证数值型数据的正常读入

2.电子表格的读取

使用read_excel函数

image

io:指定电子表格的具体路径; sheetname:指定需要读取电子表格中的第几个Sheet,可以传递整数也可以传递具体的Sheet名称; header:是否需要将数据集的第一行用作表头,默认为是需要的; skiprows:读取数据时,指定跳过的开始行数; skip_footer:读取数据是,指定跳过的末尾行数; index_col:指定哪些列用作数据框的行索引(标签); names:如果原数据集中没有字段,可以通过该参数在数据读取时给数据框添加具体的表头; parse_cols:指定需要解析的字段; parse_dates:如果参数值为True,则尝试解析数据框的行索引;如果参数为列表,则尝试解析对应的日期列;如果参数为嵌套列表,则将某些列合并为日期列;如果参数为字典,则解析对应的列(即字典中的值),并生成新的字段名(即字典中的键); na_values:指定原始数据中哪些特殊值代表了缺失值; thousands:指定原始数据集中的千分位符; convert_float:默认将所有的数值型字段转换为浮点型字段; converters:通过字典的形式,指定某些列需要转换的形式;

image




    
b=pd.read_excel(io="F:\第5章 Python数据处理工具--Pandas\第五章 Python数据处理工具--Pandas\data_test02.xlsx",header=None,converters={0:str},names=['ID',"name",'color',"price"])
b

复制代码

image

对于第一列,实际上是字符型,为了避免数据读入时自动变成数值型字段,需要用converts参数

3.数据库数据的读取

需要先通过cmd命令输入pip install pymysql或者pysmsql(分别对应MYSQL和SQL Server) CASE1:pymysql中的connect

image

host:指定需要访问的MySQL服务器; user:指定访问MySQL数据库的用户名; password:指定访问MySQL数据库的密码; database:指定访问MySQL数据库的具体库名; port:指定访问MySQL数据库的端口号; charset:指定读取MySQL数据库的字符集,如果数据库表中含有中文,一般可以尝试将该参数设置为“utf8”或“gbk”; CASE2:pymssql中的connect

image

参数含义也是一致的,所不同的是pymysql模块中connect函数的host参数表示需要访问的服务器,而pymssql函数中对应的参数是server

以MYSQL举例:

image

# 读入MySQL数据库数据
# 导入第三方模块
import pymysql
# 连接MySQL数据库
conn = pymysql.connect(host='localhost', user='root', password='test', 
                database='test', port=3306, charset='utf8')
# 读取数据
user = pd.read_sql('select * from topy', conn)
# 关闭连接
conn.close()
# 数据输出
user

复制代码

image

三、数据类型转换及描述统计

涉及如何了解数据,例如读入数据规模如何、各个变量属于什么类型、重要统计指标所对应的值、离散变量各唯一值的频次统计等等。 以某平台二手车信息为例:

#数据读取
cars=pd.read_table("F:\sec_cars.csv",sep=",")
#预览数据前5行
cars.head()

复制代码

image

后5行数据为tail

#查看数据行列数
print(cars.shape)

复制代码

image

#查看变量数据类型
print(cars.dtypes)

复制代码

image

object指字符型,但车牌时间应该为日期型,新车价格应该为浮点型,下面修改

日期类型一般通过pandas模块中的to_datetime函数,format参数可直接设置格式

#修改车牌时间
cars.Boarding_time=pd.to_datetime(cars.Boarding_time,format="%Y年%m月")

复制代码

新车价格中含有“万”字,因此不能直接转为数据类型。需要三步走,首先通过str方法将该字段转换成字符串,然后通过切片手段,将“万”字剔除,最后运用astype方法,实现数据类型的转换。

#修改新车价格
cars.New_price=cars.New_price.str[:-1].astype("float")

复制代码
#重新查看数据类型
cars.dtypes

复制代码

image

接下来,需要对数据做到心中有数,即通过基本的统计量(如最小值、均值、中位数、最大值等)描述出数据中所有数值型变量的特征。关于数据的描述性分析可以使用describe方法:

#数据的描述性统计
cars.describe()

复制代码

image

进一步了解数据的形状分布,如数据是否有偏以及是否属于“尖峰厚尾”的特征,一次性统计数值型变量的偏度和峰度

columns方法用于返回数据集的所有变量名,通过布尔索引和切片方法获得所有的数值型变量

#筛选出所有数值型变量
num_variables=cars.columns[cars.dtypes!="object"][1:]
num_variables

复制代码

image

在自定义函数中,运用到了计算偏度的skew方法和计算峰度的kurt方法,然后将计算结果组合到序列中

#自定义函数,计算偏度和峰度
def skew_kurt(x):
 skewness=x.skew()
 kurtsis=x.kurt()
 return pd.Series([skewness,kurtsis],index=["skew","kurt"])

复制代码

使用apply方法,该方法的目的就是对指定轴(axis=0,即垂直方向的各列)进行统计运算(运算函数即自定义函数)

cars[num_variables].apply(func=skew_kurt,axis=0)

复制代码

image

以上的统计分析全都是针对数值型变量的,对于字符型变量(如二手车品牌Brand、排放量Discharge等)可以使用describe方法,所不同是,需要将“object”以列表的形式传递给include参数

#离散型变量的统计描述
cars.describe(include=["object"])

复制代码

image

如上结果包含离散变量的四个统计值,分别是非缺失观测数、唯一水平数、频次最高的离散值和具体的频次。以二手车品牌为例,一共有10,984辆二手车,包含104种品牌,其中别克品牌最多,高达1,346辆。

进一步需要统计的是各个离散值的频次,甚至是对应的频率。以二手车品的标准排量Discharge为例

#离散变量频次统计
Freq=cars.Discharge.value_counts()
#总记录,总频次
cars.shape[0]
Freq_ratio = Freq/cars.shape[0]
Freq_df = pd.DataFrame({'Freq':Freq,'Freq_ratio':Freq_ratio})
Freq_df.head()

复制代码

image

构成的数据框包含两列,分别是二手车各种标准排量对应的频次和频率,数据框的行索引(标签)就是二手车不同的标准排量。如果读者需要把行标签设置为数据框中的列,可以使用reset_index方法,inplace参数设置为True,表示直接对原始数据集进行操作,影响到原数据集的变化,否则返回的只是变化预览

#将行索引重设为变量
Freq_df.reset_index(inplace=True)
#重新查看数据框
Freq_df.head()

复制代码

image

四、字符与日期数据的处理

如何基于数据框操作字符型变量,以及有关日期型数据的处理,例如如何从日期型变量中取出年份、月份、星期几等,如何计算两个日期间的时间差

df=pd.read_excel("F:\data_test03.xlsx")
#查看数据前五行
df.head()

复制代码

image

#查看数据类型
df.dtypes

复制代码

image

下面修改生日birthday为日期型,电话号码tel为字符串

#修改birthday
df.birthday=pd.to_datetime(df.birthday,format="%Y/%m/%d")
#修改tel
df.tel=df.tel.astype("str")
#重新查看数据类型
df.dtypes

复制代码

image

对于年龄和工龄的计算,需要将当前日期与出生日期和开始工作日期作减法运算,而当前日期的获得,则使用了Pandas子模块datetime中的today函数。由于计算的是相隔的年数,所以还需进一步取出日期中的年份dt.year

#根据出生日期新增年龄
df["age"]=pd.datetime.today().year-df.birthday.dt.year
#根据开始工作日期新增工龄
df["workage"]=pd.datetime.today().year-df.start_work.dt.year

复制代码

将手机号tel的中间四位隐藏起来,是字符串中的替换法(replace),由于替换法所处理的对象都是变量中的每一个观测,属于重复性工作,所以考虑使用序列的apply方法。需要注意的是,apply方法中的func参数,都是使用匿名函数,对于隐藏手机号中间四位的思路就是用星号替换手机号的中间四位

#隐藏电话号码中间4位
df.tel = df.tel.apply(func = lambda x : x.replace(x[3:7],"****"))

复制代码

对于邮箱域名的获取,是字符串中的分割法(split),其思路就是按照邮箱中的@符风格,然后取出第二个元素(即列表索引为1)

#取出邮箱域名,新增一列
df["email_domain"]=df.email.apply(func = lambda x: x.split("@")[1])

复制代码

从other变量中获取人员的专业信息,使用了字符串的正则表达式,不管是字符串“方法”还是字符串正则,在使用前都需要对变量使用一次str方法。findall是匹配查询函数,然后正则符号(.*?)用于分组,默认返回括号内的匹配内容

# 取出人员的专业信息
df['profession'] = df.other.str.findall('专业:(.*?),')

复制代码

删除数据集中的某些变量,可以使用数据框的drop方法。该方法接受的第一个参数就是被删除的变量列表,尤其要注意的是,需要将axis参数设置为1,因为默然drop方法是用来删除数据框中的行记录

# 去除birthday、start_work和other变量
df.drop(['birthday','start_work','other'], axis = 1, inplace = True)
#重新查看前五行
df.head()

复制代码

image

针对日期型数据罗列一些常用的“方法”:

image

五、常用的数据清洗方法

数据集是否存在重复、是否存在缺失、数据是否具有完整性和一致性、数据中是否存在异常值等

1.重复观测处理

df=pd.read_excel("F:\data_test04.xlsx")
#查看数据
df

复制代码

image

any函数表示的是在多个条件判断中,只要有一个条件为True,则any函数的结果就为True

#检测是否有重复观测
any(df.duplicated())

复制代码

image

删除重复项,nplace=True就表示直接在原始数据集上作操作

# 删除重复项
df.drop_duplicates(inplace = True)
df

复制代码

image

原先的10行观测,尽管排重后得到7行观测,被删除的行号为3、8和9、

2.缺失值处理

导致观测的缺失可能有两方面原因,一方面是人为原因(如记录过程中的遗漏、个人隐私而不愿透露等),另一方面是机器或设备的故障所导致(如断电或设备老化等原因)。

一般而言,当遇到缺失值(Python中用NaN表示)时,可以采用三种方法处置,分别是删除法、替换法和插补法。删除法是指当缺失的观测比例非常低时(如5%以内),直接删除存在缺失的观测,或者当某些变量的缺失比例非常高时(如85%以上),直接删除这些缺失的变量;替换法是指用某种常数直接替换那些缺失值,例如,对连续变量而言,可以使用均值或中位数替换,对于离散变量,可以使用众数替换;插补法是指根据其他非缺失的变量或观测来预测缺失值,常见的插补法有回归插补法、K近邻插补法、拉格朗日插补法等。

CASE1:删除法

df=pd.read_excel("F:\data_test05.xlsx")
#查看是否有缺失数据
any(df.isnull())

复制代码

image

分别使用两种方法实现数据集中缺失值的处理,行删除法,即将所有含缺失值的行记录全部删除,使用dropna方法;变量删除法,由于原数据集中age变量的缺失值最多,所以使用drop方法将age变量删除

#行删除法
df.dropna()

复制代码

image

#变量删除法
df.drop("age",axis=1)

复制代码

image

CASE2:替换法 缺失值的替换需要借助于fillna方法,该方法中的method参数,可以接受'ffill'和'bfill'两种值,分别代表前向填充和后向填充。前向填充是指用缺失值的前一个值替换(如左图所示),而后向填充则表示用缺失值的后一个值替换(如右图所示)。右图中的最后一个记录仍包含缺失值,是因为后向填充法找不到该缺失值的后一个值用于替换。在作者看来,缺失值的前向填充或后向填充一般适用于时间序列型的数据集,因为这样的数据前后具有连贯性,而一般的独立性样本并不适用该方法。

# 替换法之前向替换
df.fillna(method = 'ffill')

复制代码

image

# 替换法之后向替换
df.fillna(method = 'bfill')

复制代码

image

另一种替换手段,仍然是使用fillna方法,只不过不再使用method参数,而是使用value参数。使用一个常数0替换所有的缺失值。

#使用常数0替换
df.fillna(value=0)

复制代码

image

或者采用更加灵活的替换方法,即分别对各缺失变量使用不同的替换值(需要采用字典的方式传递给value参数),性别使用众数替换,年龄使用均值替换,收入使用中位数替换。

#使用统计值替换
df.fillna(value={'gender':df.gender.mode()[0], 'age':df.age.mean(), 'income':df.income.median()})

复制代码

image

需要说明的是,如上代码并没有实际改变df数据框的结果,因为dropna、drop和fillna方法并没有使inplace参数设置为True。读者可以在实际的学习和工作中挑选一个适当的缺失值处理方法,然后将该方法中的inplace参数设置为True,进而可以真正的改变你所处理的数据集。

3.异常值处理

异常值是指那些远离正常值的观测,即“不合群”观测。导致异常值的出现一般是人为的记录错误或者是设备的故障等,异常值的出现会对模型的创建和预测产生严重的后果。当然异常值也不一定都是坏事,有些情况下,通过寻找异常值就能够给业务带来良好的发展,如销毁“钓鱼”网站、关闭“薅羊毛”用户的权限等。

对于异常值的检测,一般采用两种方法: 一种是n个标准差法,标准差法的判断公式是outlinear>|x ̅±nσ|,其中x ̅为样本均值,σ为样本标准差,当n=2时,满足条件的观测就是异常值,当n=3时,满足条件的观测就是极端异常值; 另一种是箱线图判别法,箱线图的判断公式是outlinear>Q3+ nIQR或者outlinear<Q1- nIQR,其中Q1为下四分位数(25%),Q3为上四位数(75%),IQR为四分位差(上四分位数与下四分位数的差),当n=1.5时,满足条件的观测为异常值,当n=3时,满足条件的观测即为极端异常值。

image

这两种方法的选择标准如下,如果数据近似服从正态分布时,优先选择n个标准差法,因为数据的分布相对比较对称;否则优先选择箱线图法,因为分位数并不会受到极端值的影响。当数据存在异常时,一般可以使用删除法将异常值删除(前提是异常观测的比例不能太大)、替换法(可以考虑使用低于判别上限的最大值或高于判别下限的最小值替换、使用均值或中位数替换等)。

sun=pd.read_table("F:\sunspots.csv",sep=",")
sun.head()

复制代码

image

# 异常值检测之标准差法
xbar = sunspots.counts.mean()
xstd = sunspots.counts.std()
print('标准差法异常值上限检测:\n',any(sunspots.counts > xbar + 2 * xstd))
print('标准差法异常值下限检测:\n',any(sunspots.counts < xbar - 2 * xstd))
# 异常值检测之箱线图法
Q1 = sunspots.counts.quantile(q = 0.25)
Q3 = sunspots.counts.quantile(q = 0.75)
IQR = Q3 - Q1
print('箱线图法异常值上限检测:\n',any(sunspots.counts > Q3 + 1.5 * IQR))
print('箱线图法异常值下限检测:\n',any(sunspots.counts < Q1 - 1.5 * IQR))

复制代码

image

不管是标准差检验法还是箱线图检验法,都发现太阳黑子数据中存在异常值,而且异常值都是超过上限临界值的。

接下来,通过绘制太阳黑子数量的直方图和核密度曲线图,用于检验数据是否近似服从正态分布,进而选择一个最终的异常值判别方法:

#导入绘图模块
import matplotlib.pyplot as plt
#设置绘图风格
plt.style.use("ggplot")
#绘制直方图
sun.counts.plot(kind="hist",bins=30,normed=True)
#绘制核密度图
sun.counts.plot(kind="kde")
#图形展现
plt.show()

复制代码

image

不管是直方图还是核密度曲线,所呈现的数据分布形状都是有偏的,并且属于右偏。基于此,这里就选择箱线图法用以判定太阳黑子数据中的那些异常值。接下来要做的就是选用删除法或替换法来处理这些异常值

此处使用低于判别上限的最大值或高于判别下限的最小值替换

# 箱线图中的异常值判别上限
UL = Q3 + 1.5 * IQR
print('判别异常值的上限临界值:\n',UL)
# 从数据中找出低于判别上限的最大值
replace_value = sun.counts[sun.counts < UL].max()
print('用以替换异常值的数据:\n',replace_value)
# 替换超过判别上限异常值
sun.counts[sun.counts > UL] = replace_value

复制代码

image

如果使用箱线图法判别异常值,则认定太阳黑子数目一年内超过148.85时即认为是异常值年份,对于这些年份的异常值使用141.7替换。

六、数据子集的获取

通常,在Pandas模块中实现数据框子集的获取可以使用iloc、loc和ix三种“方法”,这三种方法既可以对数据行作筛选,也可以实现变量的挑选,它们的语法可以表示成[rows_select, cols_select]。

iloc只能通过行号和列号进行数据的筛选,读者可以将iloc中的“i”理解为“integer”,即只能向[rows_select, cols_select]指定整数列表。该索引方式与数组的索引方式类似,都是从0开始、可以间隔取号、对于切片仍然无法取到上限。

loc要比iloc灵活一些,读者可以将loc中的“l”理解为“label”,即可以向[rows_select, cols_select]指定具体的行标签(行名称)和列标签(字段名),注意,这里是标签不再是索引。而且,还可以将rows_select指定为具体的筛选条件,在iloc中是无法做到的。

ix是iloc和loc的混合,读者可以将ix理解为“mix”,该“方法”吸收了iloc和loc的优点,使数据框子集的获取更加的灵活。

1.原始数据的行号与行标签(名称)一致

# 构造数据集
df1 = pd.DataFrame({'name':['张三','李四','王二','丁一','李五'], 
                    'gender':['男','女','女','女','男'], 
                    'age':[23,26,22,25,27]}, columns = ['name','gender','age'])
df

复制代码

image

取出数据集中间三行,并且返回姓名和年龄指定的两列 ①iloc即索引的方法

df1.iloc[1:4,[0,2]]

复制代码

image

②loc不再是索引,直接对应行名称

df1.loc[1:3, ['name','age']]

复制代码

image

③ix效果同loc,但对变量名的筛选可用列号也可用具体变量名称

df1.ix[1:3,[0,2]]
#或者
df1.ix[1:3,['name','age']]

复制代码

image

2.原始数据的行号与行标签(名称)不一致/没有行号




    
# 将员工的姓名用作行标签
df2 = df1.set_index('name')
df2

复制代码

image

取出数据集的中间三行 ①iloc即索引的方法

df2.iloc[1:4,:]

复制代码

image

②loc使用行标签,不可再写行号

df2.loc[['李四','王二','丁一'],:]

复制代码

image

③ix此时同iloc

df2.ix[1:4,:]

复制代码

image

3.取出所有男性的性别和年龄

对某些列做条件筛选,只能使用loc和ix

df1.loc[df1.gender == '男',['name','age']]
df1.ix[df1.gender == '男',['name','age']]

复制代码

image

七、透视表功能

pd.pivot_table(data, values=None, index=None, columns=None, 
               aggfunc='mean', fill_value=None, margins=False, 
               dropna=True, margins_name='All')

复制代码

data:指定需要构造透视表的数据集; values:指定需要拉入“数值”框的字段列表; index:指定需要拉入“行标签”框的字段列表; columns:指定需要拉入“列标签”框的字段列表; aggfunc:指定数值的统计函数,默认为统计均值,也可以指定Numpy模块中的其他统计函数; fill_value:指定一个标量,用于填充缺失值; margins:bool类型参数,是否需要显示行或列的总计值,默认为False; dropna:bool类型参数,是否需要删除整列为缺失的字段,默认为True; margins_name:指定行或列的总计名称,默认为All;

1.单个分组变量的均值统计

基于单个分组变量color的汇总统计(price的均值)

diamonds=pd.read_table("F:\diamonds.csv",sep=",")
diamonds.head()

复制代码

image

# 单个分组变量的均值统计
pd.pivot_table(data = diamonds, index = 'color', values = 'price', margins = True, margins_name = '总计')

复制代码

image

2.两个分组变量的列联表

对于列联表来说,行和列都需要指定某个分组变量,所以index参数和columns参数都需要指定一个分组变量。并且统计的不再是某个变量的均值,而是观测个数,所以aggfunc参数需要指定numpy模块中的size函数。通过这样的参数设置

# 两个分组变量的列联表
# 导入numpy模块
import numpy as np
pd.pivot_table(data = diamonds, index = 'clarity', columns = 'cut', values = 'carat', 
               aggfunc = np.size,margins = True, margins_name = '总计')

复制代码

image

八、表之间的合并和连接

对于多表之间的纵向合并,则必须确保多表的列数和数据类型一致;对于多表之间的水平扩展,则必须保证多表要有共同的匹配字段。Pandas模块同样提供了关于多表之间的合并和连接操作函数,分别是concat函数和merge函数。

1.合并函数concat

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None)

复制代码

objs:指定需要合并的对象,可以是序列、数据框或面板数据构成的列表; axis:指定数据合并的轴,默认为0,表示合并多个数据的行,如果为1,则表示合并多个数据的列; join:指定合并的方式,默认为outer,表示合并所有数据,如果改为inner,表示合并公共部分的数据; join_axes:合并数据后,指定保留的数据轴; ignore_index:bool类型的参数,表示是否忽略原数据集的索引,默认为False,如果设为True,则表示忽略原索引并生成新索引; keys:为合并后的数据添加新索引,用于区分各个数据部分;

# 构造数据集df1和df2
df1 = pd.DataFrame({'name':['张三','李四','王二'], 'age':[21,25,22], 'gender':['男','女','男']})
df2 = pd.DataFrame({'name':['丁一','赵五'], 'age':[23,22], 'gender':['女','女']})
# 数据集的纵向合并
pd.concat([df1,df2] , keys = ['df1','df2'])

复制代码

image

为了区分合并后的df1数据集和df2数据集,代码中的concat函数使用了keys参数,如果再设置参数ignore_index为True,此时keys参数将不再有效

pd.concat([df1,df2] , keys = ['df1','df2'],ignore_index=True)

复制代码

image

2.连接函数merge

函数的最大缺点是,每次只能操作两张数据表的连接,如果有n张表需要连接,则必须经过n-1次的merge函数使用

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

复制代码

left:指定需要连接的主表; right:指定需要连接的辅表; how:指定连接方式,默认为inner内连,还有其他选项,如左连left、右连right和外连outer; on:指定连接两张表的共同字段; left_on:指定主表中需要连接的共同字段; right_on:指定辅表中需要连接的共同字段; left_index:bool类型参数,是否将主表中的行索引用作表连接的共同字段,默认为False; right_index:bool类型参数,是否将辅表中的行索引用作表连接的共同字段,默认为False; sort:bool类型参数,是否对连接后的数据按照共同字段排序,默认为False suffixes:如果数据连接的结果中存在重叠的变量名,则使用各自的前缀进行区分;

# 构造数据集
df3 = pd.DataFrame({'id':[1,2,3,4,5],'name':['张三','李四','王二','丁一','赵五'],'age':[27,24,25,23,25],'gender':['男','男','男','女','女']})
df4 = pd.DataFrame({'Id':[1,2,2,4,4,4,5],'kemu':['科目1','科目1','科目2','科目1','科目2','科目3','科目1'],'score':[83,81,87,75,86,74,88]})
df5 = pd.DataFrame({'id':[1,3,5],'name':['张三','王二','赵五'],'income':[13500,18000,15000]})
# 三表的数据连接
# 首先df3和df4连接
merge1 = pd.merge(left = df3, right = df4, how = 'left', left_on='id', right_on='Id')
merge1

复制代码

image

# 再将连接结果与df5连接
merge2 = pd.merge(left = merge1, right = df5, how = 'left')
merge2

复制代码

image

如果需要将这三张表横向扩展到一张宽表中,需要经过两次的merge操作。如上代码所示,第一次merge连接了df3和df4,由于两张表的共同字段不一致,所以需要分别指定left_on和right_on的参数值;第二次merge连接了首次的结果和df5,此时并不需要指定left_on和right_on参数,是因为第一次的merge结果就包含了id变量,所以merge时会自动挑选完全一致的变量用于表连接。

九、分组聚合操作

在数据库中还有一种非常常见的操作就是分组聚合,即根据某些个分组变量,对数值型变量进行分组统计。以珠宝数据为例,统计各颜色和刀工组合下的珠宝数量、最小x、平均价格和最大深度

需结合使用Pandas模块中的groupby“方法”和aggregate“方法”

使用Pandas实现分组聚合需要分两步走,第一步是指定分组变量,可以通过数据框的groupby“方法”完成;第二步是对不同的数值变量计算各自的统计值,在第二步中,需要跟读者说明的是,必须以字典的形式控制变量名称和统计函数

# 通过groupby方法,指定分组变量
grouped = diamonds.groupby(by = ['color','cut'])
# 对分组变量进行统计汇总
result = grouped.aggregate({'color':np.size, 'x':np.min, 'price':np.mean, 'depth':np.max})
result

复制代码

image

....

# 数据集重命名
result.rename(columns={'color':'counts','x':'min_x','price':'avg_price','depth':'max_depth'}, inplace=True)
result

复制代码

image

... 分组变量color和cut成了数据框的行索引。如果需要将这两个行索引转换为数据框的变量名,可以使用数据框的reset_index方法

# 将行索引变量数据框的变量
result.reset_index(inplace=True)
result

复制代码

image

...

总结

pandas模块

Series  生成序列类型的函数
DataFrame   生成数据框类型的函数
read_table  读取文本文件的函数,如txt、csv等
read_csv    读取文本文件的函数,如txt、csv等
read_excel  读取电子表格的函数

复制代码

pymysql/pmssql模块

connect 数据库与Python的连接函数
close   关闭数据库与Python之间连接的“方法”

复制代码

pandas模块




    
read_sql    读取数据库数据的函数
head/tail   显示数据框首/末几行的“方法”
shape   返回数据框行列数的“方法”
dtypes  返回数据框中各变量数据类型的“方法”
to_datetime 将变量转换为日期时间型的函数
astype  将变量转换为其他类型的“方法”
describe    统计性描述的“方法”
columns 返回数据框变量名的“方法”
index   返回数据框行索引的“方法”
apply   序列或数据框的映射“方法”
value_counts    序列值频次统计的“方法”
reset_index 将行索引转换为变量的“方法”
duplicated  检验观测是否重复的“方法”
drop_duplicates 删除重复项的“方法”
drop    删除变量名或观测的“方法”
dropna  删除缺失值的“方法”
fillna  填充缺失值的“方法”
quantile    统计序列分位数的“方法”
plot    序列或数据框的绘图“方法”
iloc/loc/ix 数据框子集获取的“方法”
pivot_table 构建透视表的函数
concat  实现多表纵向合并的函数
merge   实现两表水平扩展的函数
groupby 分组聚合时,指定分组变量的“方法”
aggregate   指定聚合统计的“方法”
rename  修改数据框变量名的“方法”
复制代码
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/107213
 
442 次点击