pandas的拼接分为两种:
import numpy as np
nd1 = np.array([1,2,3])
nd2 = np.array([-1,-2,-3,-4])
np.concatenate([nd1,nd2],axis=0)
nd3 = np.array([[1,2,3],[4,5,6]])
nd3
np.concatenate([nd1,nd3],axis=1) # 维度不同无法级联
nd4 = np.random.randint(0,10,size=(3,3))
nd4
np.concatenate([nd3,nd4],axis=0)
nd3 + nd4
nd1 + nd3 # 维度不一样可以广播机制
============================================
练习12:
============================================
为方便讲解,我们首先定义一个生成DataFrame的函数:
import pandas as pd
from pandas import DataFrame,Series
# 定义一个函数,根据行he列名对元素设置值
def make_df(cols,inds):
data = {c:[c+str(i) for i in inds] for c in cols}
return DataFrame(data,index=inds)
df1 = make_df(list("abc"),[1,2,4])
df1
df2 = make_df(list("abc"),[4,5,6])
df2
pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
keys=None, levels=None, names=None, verify_integrity=False,
copy=True)
和np.concatenate一样,优先增加行数(默认axis=0)
pd.concat([df1,df2])
pd.concat([df1,df2],axis=1)
可以通过设置axis来改变级联方向
注意index在级联时可以重复
也可以选择忽略ignore_index,重新索引
pd.concat([df1,df2],axis=0,ignore_index=True)
或者使用多层索引 keys
concat([x,y],keys=['x','y'])
pd.concat([df1,df2],keys=["教学","品保"])
============================================
练习13:
想一想级联的应用场景?
使用昨天的知识,建立一个期中考试张三、李四的成绩表ddd
假设新增考试学科"计算机",如何实现?
新增王老五同学的成绩,如何实现?
============================================
不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致
df1
df3 = make_df(list("abcd"),[1,2,3,4])
df3
pd.concat([df1,df3],axis=0)
pd.concat([df1,df3],axis=1)
有3种连接方式:
pd.concat([df1,df3],axis=0,join="outer")
# 1、不匹配级联在外连接的模式下要求如果axis=0行级联列索引必须保持一致,
#axis=1列级联行索引必须保持一致
# 2、如果不一致缺哪个索引就补全哪个索引
pd.concat([df1,df3],axis=0,join="inner")
# 内连接在级联的时候不一致的地方全部丢弃
df4 = make_df(list("aecd"),[1,2,3,4])
df4
pd.concat([df3,df4],axis=0,join="inner")
df5 = make_df(list("abcf"),[2,3,4,8])
df5
pd.concat([df1,df4,df5],axis=1,join_axes=[df1.index])
df1
df1.append(df4)
df1.append(df4,axis=1) # append函数没有axis属性,只能对行进行级联
============================================
练习14:
假设【期末】考试ddd2的成绩没有张三的,只有李四、王老五、赵小六的,使用多种方法级联
============================================
由于在后面级联的使用非常普遍,因此有一个函数append专门用于在后面添加
merge与concat的区别在于,merge需要依据某一共同的行或列来进行合并
使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。
注意每一列元素的顺序不要求一致
如果在合并的时候,另个表的key那一列对应的值完全一样,这个合并就是一对一合并
df1 = DataFrame({
"name":["Jack Ma","Gates Bill","MrsWang","Xiaoming"],
"age":[50,60,48,18],
"sex":["男","男","女","男"],
"weight":[60,68,80,50]
})
df1
df2 = DataFrame({
"name":["Jack Ma","Gates Bill","MrsWang","Xiaoming"],
"home":["杭州","美国","隔壁","河南"],
"work":["teacher","seller","boss","student"],
})
df2
pd.concat([df1,df2],axis=1)
df1.merge(df2)
pd.merge(df1,df2)
表1中的某些属性的值,在表2中有多个和他对应,此时就是一对多合并
在合并的时候,首先要把“一”的哪一方不足的属性值根据已有的属性进行复制,然后在合并
df3 = DataFrame({
"name":["Jack Ma","Gates Bill","MrsWang","Xiaoming","Xiaoming","Jack Ma"],
"home":["杭州","美国","隔壁","河南","山东","安徽"],
"work":["teacher","seller","boss","student","studet","boss"],
})
df3
df1.merge(df3)
表1中某些属性有多个值,在表2中对应的值也有多个,这时就是多对多合并
依次拿出表1中的多个值去和表2的多个值匹配
df4 = DataFrame({
"name":["Jack Ma","Gates Bill","MrsWang","Xiaoming","Jack Ma","Jack Ma","Xiaoming"],
"age":[50,60,48,18,20,30,40],
"sex":["男","男","女","男","M","M","F"],
"weight":[60,68,80,50,40,50,30]
})
df4
df3
df4.merge(df3)
df1
df5 = DataFrame({
"name":["Jack Ma","Gates Bill","MrsWang","Xiaoming","Xiaoming","Jack Ma"],
"home":["杭州","美国","隔壁","河南","山东","安徽"],
"work":["teacher","seller","boss","student","studet","boss"],
"age":[15,67,89,12,34,56]
})
df5
# 如果两个表有多个相同的属性,需要指定以哪一个属性为基准来合并
df1.merge(df5,on="name",suffixes=["_实际","_假的"])
df6 = DataFrame({
"姓名":["Jack Ma","Gates Bill","MrsWang","Xiaoming","Xiaoming","Jack Ma"],
"home":["杭州","美国","隔壁","河南","山东","安徽"],
"work":["teacher","seller","boss","student","studet","boss"],
})
df6
df1
df1.merge(df6,left_on="name",right_on="姓名")
# 如果两个表没有相同的属性,可以左边的表出一个属性,右边的表出一个属性,然后进行合并
# 这种合并两个属性不能并在一起
df1.merge(df6,left_on="age",right_on="home") # 没有相同的值,和出来是空
df1.merge(df6,right_index=True,left_index=True) # 用索引来合并
============================================
练习16:
假设有两份成绩单,除了ddd是张三李四王老五之外,还有ddd4是张三和赵小六的成绩单,如何合并?
如果ddd4中张三的名字被打错了,成为了张十三,怎么办?
自行练习多对一,多对多的情况
自学left_index,right_index
============================================
df7 = DataFrame({
"name":["Jack Ma","Gates Bill","MrsWang","Xiaoming","Xiaowang","MaYun"],
"home":["杭州","美国","隔壁","河南","山东","安徽"],
"work":["teacher","seller","boss","student","studet","boss"],
})
df7
df1.merge(df7,how="inner")
df1.merge(df7,how="outer")
df1["name"][0] = "Peater"
df1
df1.merge(df7,how="right")
# 左和并:以左侧为基准,左侧有右侧没有补nan,左侧没有右侧有去掉
# 有合并:和上面相反
============================================
练习17:
如果只有张三赵小六语数英三个科目的成绩,如何合并?
考虑应用情景,使用多种方式合并ddd与ddd4
============================================
当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
可以使用suffixes=自己指定后缀
============================================
练习18:
假设有两个同学都叫李四,ddd5、ddd6都是张三和李四的成绩表,如何合并?
============================================
首先导入文件,并查看数据样本
abbr = pd.read_csv("./usapop/state-abbrevs.csv")
abbr.head()
areas = pd.read_csv("./usapop/state-areas.csv")
areas.head()
pop = pd.read_csv("./usapop/state-population.csv")
pop.head()
合并pop与abbrevs两个DataFrame,分别依据state/region列和abbreviation列来合并。
为了保留所有信息,使用外合并。
pop2 = pop.merge(abbr,left_on="state/region",right_on="abbreviation",how="outer")
# 用外连接(或者左链接)
pop2
去除abbreviation的那一列(axis=1)
pop2.drop("abbreviation",axis=1,inplace=True)
# 默认axis=0删除行
# inplace是否在原表上删除,默认是False不在原表上删除
pop2.head()
查看存在缺失数据的列。
使用.isnull().any(),只有某一列存在一个缺失数据,就会显示True。
cond = pop2.isnull().any(axis=1)
cond
pop2[cond]
查看缺失数据
根据数据是否缺失情况显示数据,如果缺失为True,那么显示
cond_state = pop2["state"].isnull()
找到有哪些state/region使得state的值为NaN,使用unique()查看非重复值
pop2[cond_state]["state/region"].unique()
为找到的这些state/region的state项补上正确的值,从而去除掉state这一列的所有NaN!
记住这样清除缺失数据NaN的方法!
cond_pr = pop2["state/region"] == "PR"
cond_usa = pop2["state/region"] == "USA"
pop2["state"][cond_pr] = "Puerto Rico"
pop2["state"][cond_usa] = "United State"
pop2.head()
pop2.isnull().any()
合并各州面积数据areas,使用左合并。
思考一下为什么使用外合并?
areas.head()
pop3 = pop2.merge(areas,how="outer")
pop3.head()
继续寻找存在缺失数据的列
pop3.isnull().any()
cond_area = pop3["area (sq. mi)"].isnull()
pop3[cond_area]
我们会发现area(sq.mi)这一列有缺失数据,为了找出是哪一行,我们需要找出是哪个state没有数据
# usa面积缺失,就可以吧所有的州面积求和
usa_area = areas["area (sq. mi)"].sum()
# 把美国的面积赋值到pop3中
pop3["area (sq. mi)"][cond_area] = usa_area
pop3
去除含有缺失数据的行
pop3.isnull().any()
查看数据是否缺失
pop3.dropna(inplace=True)
pop3.isnull().any()
找出2010年的全民人口数据,df.query(查询语句)
pop3.head()
pop3.query("year==2010 & ages=='total' & state=='United State'")
pop_2010 = pop3.query("year==2010 & ages=='total'")
pop_2010
对查询结果进行处理,以state列作为新的行索引:set_index
pop_2010.set_index("state",inplace=True)
pop_2010.shape
计算人口密度。注意是Series/Series,其结果还是一个Series。
pop_dense = pop_2010["population"] / pop_2010["area (sq. mi)"]
pop_dense
排序,并找出人口密度最高的五个州sort_values()
pop_dense.sort_values(inplace=True)
pop_dense
pop_dense.tail()
找出人口密度最低的五个州
pop_dense.head()
要点总结: