学堂 学堂 学堂公众号手机端

【Python】数据分析.pandas数据预处理.数据组合

lewis 1年前 (2024-04-09) 阅读数 14 #技术




文章目录​​数据分析.pandas数据预处理.数据合并​​​​一、数据堆叠 concat()、append()​​​​二、主键连接 --- join()​​​​三、主键连接 --- merge()​​​​四、重叠合并数据combine_first()​​
数据分析.pandas数据预处理.数据合并一、数据堆叠 concat()、append()

堆叠就是简单地把两个表拼在一起,也被称作轴向连接、绑定或连接。依照轴的方向,数据堆叠可以分为横向堆叠和纵向堆叠。


concat方法相当于数据库中的全连接(UNION ALL),可以指定按某个轴进行连接。



下面以该表为例演示:


当axis=1的时候,concat作行对齐,然后将不同名称的两张或多张表合并。当两个表的索引不完全一致时,可以使用join来指定连接方式:内连接(inner交集)、外连接(outer并集)。内连接仅仅返回多表间索引重叠的部分,外连接则返回索引的并集部分数据,不足的部分使用空值填补。若多表的索引完全一致时,不论内连接还是外连接,结果都是将表按照x轴向拼接。

import numpy as np
import pandas as pd
from sqlalchemy import create_engine

# 创建数据库连接
engine = create_engine('mysql+pymysql://root:12345678@127.0.0.1:3306/testdb?charset=utf8')

# 读取mysql数据
detail = pd.read_sql('meal_order_detail1',con=engine)
df1 = detail.iloc[:,:10] # 取出前10列数据
df2 = detail.iloc[:,10:] # 取出后9列数据

print('合并df1的大小为%s,df2的大小为%s。'%(df1.shape,df2.shape))
print('外连接后的数据框大小为:',pd.concat([df1,df2],axis=1,join='outer').shape)
print('内连接后的数据框大小为:',pd.concat([df1,df2],axis=1,join='inner').shape)

合并df1的大小为(2779, 10),df2的大小为(2779, 9)。
外连接后的数据框大小为: (2779, 19)
内连接后的数据框大小为: (2779, 19)


当axis=0时(默认),concat做列对齐,将不同行索引的两张或多张表纵向合并。当表的列名不完全一致时,同样可以使用join参数:内连接(inner交集)、外连接(outer并集)。内连接仅仅返回多表间索引重叠的部分,外连接则返回索引的并集部分数据,不足的部分使用空值填补。若多表的索引完全一致时,不论内连接还是外连接,结果都是将表按照y轴向拼接。

df3 = detail.iloc[:1500,:] # 取出前1500行数据
df4 = detail.iloc[1500:,:] # 取出后1500行数据

print('合并df3的大小为%s,df4的大小为%s。'%(df3.shape,df4.shape))
print('内连接纵向合并数据后的数据框大小为:',pd.concat([df3,df4],axis=0,join='outer').shape)
print('外连接纵向合并数据后的数据框大小为:',pd.concat([df3,df4],axis=0,join='inner').shape)

合并df3的大小为(1500, 19),df4的大小为(1279, 19)。
内连接纵向合并数据后的数据框大小为: (2779, 19)
外连接纵向合并数据后的数据框大小为: (2779, 19)

除了可以使用concat纵向堆叠外,还可以使用append方法实现总向表的堆叠,但前提是两张表的列名必须完全一致。

pandas.DataFrame.append(self,other,ignore_index,verify_integrity=False)

print('合并df3的大小为%s,df4的大小为%s。'%(df3.shape,df4.shape))
print('append纵向堆叠后的数据框大小为:',df3.append(df4).shape)

合并df3的大小为(1500, 19),df4的大小为(1279, 19)。
append纵向堆叠后的数据框大小为: (2779, 19)

​​返回顶部​​


二、主键连接 — join()

join方法提供了一个简便的方法用于将两个DataFrame中的不同的列索引合并成为一个DataFrame。其中参数的意义与merge方法基本相同,只是join方法默认为左外连接how=left

import numpy as np
import pandas as pd

#创建三个数组
t1 = pd.DataFrame(np.ones((2,4)),index=["A","B"],columns=list("abcd"))
print(t1)
# a b c d
# A 1.0 1.0 1.0 1.0
# B 1.0 1.0 1.0 1.0
t2 = pd.DataFrame(np.ones((3,3)),index=["A","B","c"],columns=list("123"))
print(t2)
# 1 2 3
# A 1.0 1.0 1.0
# B 1.0 1.0 1.0
# c 1.0 1.0 1.0
t3 = pd.DataFrame(np.ones((3,3)),index=["0","1","2"],columns=list("123"))
print(t3)
# 1 2 3
# 0 1.0 1.0 1.0
# 1 1.0 1.0 1.0
# 2 1.0 1.0 1.0

# join()
#以最前面的数据为基础,数据的合并默认情况下是把行索引相同的数据合并到一起
print(t1.join(t2)) #t1有两行,只合并数据的前两行
# a b c d 1 2 3
# A 1.0 1.0 1.0 1.0 1.0 1.0 1.0
# B 1.0 1.0 1.0 1.0 1.0 1.0 1.0
print(t2.join(t1)) #t2有三行,合并数据,缺少的用nan值填补
# 1 2 3 a b c d
# A 1.0 1.0 1.0 1.0 1.0 1.0 1.0
# B 1.0 1.0 1.0 1.0 1.0 1.0 1.0
# c 1.0 1.0 1.0 NaN NaN NaN NaN
print(t1.join(t3)) #数据的合并默认情况下是把行索引相同的数据合并到一起,不一样索引的用nan填充
# a b c d 1 2 3
# A 1.0 1.0 1.0 1.0 NaN NaN NaN
# B 1.0 1.0 1.0 1.0 NaN NaN NaN

​​返回顶部​​


三、主键连接 — merge()

pandas提供了一个类似于关系数据库的连接(join)操作的方法merage,可以根据一个或多个键将不同DataFrame中的行连接起来,语法如下:

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

作为一个功能完善、强大的语言,python的pandas库中的merge()支持各种内外连接。

​​与数据库表的连接操作见博客----MYSQL 的连接~​​在SQL中表的关系:
一对一:在对两个表根据索引相加操作时,索引下的值必须唯一。
多对一:在对两个表进行相加操作时,其中一个表的索引下有一个或者多个相同的值。
多对多:在对两个表进行相加操作时,两个表的索引下有多个相同的值。

表的相加操作其实是对两个表进行笛卡尔乘积运算,然后根据条件筛选。

SELECT *
FROM df1
INNER JOIN df2
ON df1.key = df2.key;

SELECT *
FROM df1,df2 where df1.key=df2.key
一对一

left = pd.DataFrame({"A":["A0","A1","A2","A3"],"B":["B0","B1","B2","B3"],"Key":["k0","k1","k2","k3"]})
right = pd.DataFrame({"C":["C0","C1","C2","C3"],"D":["D0","D1","D2","D3"],"Key":["k0","k1","k2","k3"]})
print(left)
# A B Key
# 0 A0 B0 k0
# 1 A1 B1 k1
# 2 A2 B2 k2
# 3 A3 B3 k3
print(right)
# C D Key
# 0 C0 D0 k0
# 1 C1 D1 k1
# 2 C2 D2 k2
# 3 C3 D3 k3
print(pd.merge(left,right,on="Key"))
# A B Key C D
# 0 A0 B0 k0 C0 D0
# 1 A1 B1 k1 C1 D1
# 2 A2 B2 k2 C2 D2
# 3 A3 B3 k3 C3 D3

通过设置on这个参数来定义在哪个索引值下对两个表进行相加操作。除可以在一个索引值下相加之外,还可以对表在多个索引值下进行相加。

left = pd.DataFrame({"A":["A0","A1","A2","A3"],"B":["B0","B1","B2","B3"],"Key1":["k0","k0","k1","k2"],"Key2":["k0","k1","k0","k1"]})
right = pd.DataFrame({"C":["C0","C1","C2","C3"],"D":["D0","D1","D2","D3"],"Key1":["k0","k1","k1","k3"],"Key2":["k0","k0","k0","k0"]})
print(left)
# A B Key1 Key2
# 0 A0 B0 k0 k0
# 1 A1 B1 k0 k1
# 2 A2 B2 k1 k0
# 3 A3 B3 k2 k1
print(right)
# C D Key1 Key2
# 0 C0 D0 k0 k0
# 1 C1 D1 k1 k0
# 2 C2 D2 k1 k0
# 3 C3 D3 k3 k0
print(pd.merge(left,right,on=["Key1","Key2"]))
# A B Key1 Key2 C D
# 0 A0 B0 k0 k0 C0 D0
# 1 A2 B2 k1 k0 C1 D1
# 2 A2 B2 k1 k0 C2 D2

不论是单索引值还是多索引值下,表的相加都是先生成两个表的笛卡尔乘积,在判断索引值是否相等,将相等的行放入相加的结果中。

how指的是合并(连接)的方式有inner(内连接),left(左外连接),right(右外连 接),outer(全外连接);默认为inner。

left = pd.DataFrame({"A":["A0","A1","A2","A3"],"B":["B0","B1","B2","B3"],"Key1":["k0","k0","k1","k2"],"Key2":["k0","k1","k0","k1"]})
right = pd.DataFrame({"C":["C0","C1","C2","C3"],"D":["D0","D1","D2","D3"],"Key1":["k0","k1","k1","k3"],"Key2":["k0","k0","k0","k0"]})
print(left)
# A B Key1 Key2
# 0 A0 B0 k0 k0
# 1 A1 B1 k0 k1
# 2 A2 B2 k1 k0
# 3 A3 B3 k2 k1
print(right)
# C D Key1 Key2
# 0 C0 D0 k0 k0
# 1 C1 D1 k1 k0
# 2 C2 D2 k1 k0
# 3 C3 D3 k3 k0
print(pd.merge(left,right,on=["Key1","Key2"])) #默认how=“inner”
# A B Key1 Key2 C D
# 0 A0 B0 k0 k0 C0 D0
# 1 A2 B2 k1 k0 C1 D1
# 2 A2 B2 k1 k0 C2 D2

print(pd.merge(left,right,on=["Key1","Key2"],how="left")) #左外连接
# A B Key1 Key2 C D
# 0 A0 B0 k0 k0 C0 D0
# 1 A1 B1 k0 k1 NaN NaN
# 2 A2 B2 k1 k0 C1 D1
# 3 A2 B2 k1 k0 C2 D2
# 4 A3 B3 k2 k1 NaN NaN
print(pd.merge(left,right,on=["Key1","Key2"],how="right")) #右外链接
# A B Key1 Key2 C D
# 0 A0 B0 k0 k0 C0 D0
# 1 A2 B2 k1 k0 C1 D1
# 2 A2 B2 k1 k0 C2 D2
# 3 NaN NaN k3 k0 C3 D3
print(pd.merge(left,right,on=["Key1","Key2"],how="inner")) #内连接---交集
# A B Key1 Key2 C D
# 0 A0 B0 k0 k0 C0 D0
# 1 A2 B2 k1 k0 C1 D1
# 2 A2 B2 k1 k0 C2 D2
print(pd.merge(left,right,on=["Key1","Key2"],how="outer")) #外连接---并集
# A B Key1 Key2 C D
# 0 A0 B0 k0 k0 C0 D0
# 1 A1 B1 k0 k1 NaN NaN
# 2 A2 B2 k1 k0 C1 D1
# 3 A2 B2 k1 k0 C2 D2
# 4 A3 B3 k2 k1 NaN NaN
# 5 NaN NaN k3 k0 C3 D3
import numpy as np
import pandas as pd
from sqlalchemy import create_engine

# 创建数据库连接
engine = create_engine('mysql+pymysql://root:12345678@127.0.0.1:3306/testdb?charset=utf8')

# 读取mysql、csv数据
detail = pd.read_sql('meal_order_detail1',con=engine)
order = pd.read_csv('data/meal_order_info.csv',sep=',',encoding='gb18030')

# 将info_id转换为字符串格式,为合并做准备
order['info_id'] = order['info_id'].astype('str')

# 订单详情表和订单信息表均有订单编号--索引一致
order_detail = pd.merge(detail,order,left_on='order_id',right_on='info_id')

print('detail订单详情表的原始形状为:',detail.shape)
print('order订单信息表的原始形状为:',order.shape)
print('订单详情表和订单信息表主键合并后的形状为:',order_detail.shape)
order_detail.to_csv('data/order_detail.csv',sep=',',index=True)

在合并表的时候,根据detail表和info表的共有id(不考虑重复,detail表如图一id有重复,info表如图二id唯一)合并数据,于是在合并的时候重复id后的空值均以info的数值填充。




当我们将info_id改成order_id,再次执行上面的代码时,结果出现了一丝偏差。因为主键合并,是通过一个或多个键将两个数据集进行连接起来,类似于sql中的join。针对两张包含不同字段的表,将其根据某几个字段一一对应拼接起来,结果集的列数为两个原数据的列数和减去连接键的数量。

import numpy as np
import pandas as pd
from sqlalchemy import create_engine

# 创建数据库连接
engine = create_engine('mysql+pymysql://root:12345678@127.0.0.1:3306/testdb?charset=utf8')

# 读取mysql、csv数据
detail = pd.read_sql('meal_order_detail1',con=engine)
order = pd.read_csv('data/meal_order_info.csv',sep=',',encoding='gb18030')

# 将info_id转换为字符串格式,为合并做准备
order['order_id'] = order['order_id'].astype('str')

# 订单详情表和订单信息表均有订单编号--索引一致
#order_detail = pd.merge(detail,order,left_on='order_id',right_on='order_id')
order_detail = pd.merge(detail,order,on='order_id')

print('detail订单详情表的原始形状为:',detail.shape)
print('order订单信息表的原始形状为:',order.shape)
print('订单详情表和订单信息表主键合并后的形状为:',order_detail.shape)
order_detail.to_csv('data/order_detail.csv',sep=',',index=True)

detail订单详情表的原始形状为: (2779, 19)
order订单信息表的原始形状为: (945, 21)
订单详情表和订单信息表主键合并后的形状为: (2779, 39)


可以清晰地看到此时的连接表只剩下一个order_id,并且合并后的总列数变成了39,与之前不同,当我们把两张表的id设为相同时,使用merge就和join一样,当然仅限于两表所关联的主键一致时。


​​返回顶部​​


四、重叠合并数据combine_first()

有时候,某两份数据的内容完全一致,但是某些特征在其中一张表上是完整的,而在另一张表上的数据则是缺失的。这是除了使用一对一比较填充外,还可以使用重叠合并数据。

pandas.DataFrame.combine_first(other)

参数名称

说明

other

接受DataFrame。表示参与重叠合并的另一个DataFrame。无默认。

#数据填充
s1 = pd.Series([2, np.nan, 4, np.nan], index=['A', 'B', 'C', 'D'])
s2 = pd.Series([1, 2, 3, 4], index=['A', 'B', 'C', 'D'])

# 用 s2 中的数值来填充 s1
print(s1.combine_first(s2))
'''
A 2.0
B 2.0
C 4.0
D 4.0
dtype: float64
'''

df1 = pd.DataFrame({
'X':[1, np.nan, 3, np.nan],
'Y':[5, np.nan, 7, np.nan],
'Z':[9, np.nan, 11, np.nan]
})
df2 = pd.DataFrame({
'Z':[np.nan, 10, np.nan, 12],
'A':[1, 2, 3, 4]
})
# 功能同样是填充
print(df1.combine_first(df2))
'''
A X Y Z
0 1.0 1.0 5.0 9.0
1 2.0 NaN NaN 10.0
2 3.0 3.0 7.0 11.0
3 4.0 NaN NaN 12.0
'''

注意: Combine Series values, choosing the calling Series's values first.合并时优先选择调用序列的值。

​​返回顶部​​



版权声明

本文仅代表作者观点,不代表博信信息网立场。

热门