【pandas】16 pandas数据保存和拼接
2023.1.14 数据保存和读取;三种拼接方式:concat/merge/join
总结于:https://mofanpy.com/tutorials/data-manipulation/pandas/merge
16.1 读取和保存数据
16.1.1 Excel
【从文件读取数据】:pd.read_excel()
import os
os.listdir("data")
['covid19_day_wise.csv', '体检数据.xlsx']
import pandas as pd
df = pd.read_excel("data/体检数据.xlsx",index_col=0)
df
|
姓名 |
身高 |
体重 |
肺活量 |
学号 |
|
|
|
|
1 |
小明 |
168 |
60 |
3200 |
2 |
小黄 |
187 |
80 |
3800 |
3 |
小花 |
170 |
70 |
3400 |
index_col=0
:这里面是第几列当索引;编号是从第0列开始;
- 不如不填会自动生成:
df = pd.read_excel("data/体检数据.xlsx")
df
|
学号 |
姓名 |
身高 |
体重 |
肺活量 |
0 |
1 |
小明 |
168 |
60 |
3200 |
1 |
2 |
小黄 |
187 |
80 |
3800 |
2 |
3 |
小花 |
170 |
70 |
3400 |
【保存数据】:文件名.to_excel
df.to_excel("data/体检数据_修改.xlsx")
16.1.2 csv或txt等纯文本文件
- 读取:
pd.read_csv
- 存储:
文件名.to_csv
df_csv = pd.read_csv("data/体检数据.csv", index_col=0)
df_csv
|
姓名 |
身高 |
体重 |
肺活量 |
学号 |
|
|
|
|
1 |
小明 |
168 |
60 |
3200 |
2 |
小黄 |
187 |
80 |
3800 |
3 |
小花 |
170 |
70 |
3400 |
- 有时候不是标准模式
比如用=
号隔开的的文本。用sep="="
,读出的数据是以=隔开的
df_csv = pd.read_csv("data/体检数据_sep.csv", index_col=0, sep="=")
df_txt.to_csv("data/体检数据_sep_修改.csv")
16.1.3 读网上数据
df = pd.read_html("https://mofanpy.com/tutorials/data-manipulation/pandas/read-save/")
df
[ 学号 姓名 身高 体重 肺活量
0 1 小明 168 60 3200
1 2 小黄 187 80 3800
2 3 小花 170 70 3400]
16.2 融合数据 Concat 和 Merge
- 拼接
Concat
:函数可以沿着指定的轴将多个dataframe或者series拼接到一起。
- 融合
Merge
- 接入
Join
16.2.1拼接Concat
pd.concat( objs, axis=0, join=‘outer’, join_axes=None,ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=None, copy=True,)
- objs 表示需要连接的对象,比如:[df1, df2],需要将合并的数据用综括号包围;
- axis=0 表拼接方式是上下堆叠,当axis=1表示左右拼接;
- join 参数控制的是外连接还是内连接,join='outer’表示外连接,保留两个表中的所有信息;join="inner"表示内连接,拼接结果只保留两个表共有的信息;
- 【上下拼接】
df1 = pd.DataFrame({
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
}, index=[0, 1, 2, 3],)
df2 = pd.DataFrame({
"A": ["A4", "A5", "A6", "A7"],
"B": ["B4", "B5", "B6", "B7"],
"C": ["C4", "C5", "C6", "C7"],
"D": ["D4", "D5", "D6", "D7"],
}, index=[3, 5, 6, 7],)
df3 = pd.DataFrame({
"A": ["A8", "A9", "A10", "A11"],
"B": ["B8", "B9", "B10", "B11"],
"C": ["C8", "C9", "C10", "C11"],
"D": ["D8", "D9", "D10", "D11"],
}, index=[8, 9, 10, 11],)
pd.concat([df1, df2, df3])
|
A |
B |
C |
D |
0 |
A0 |
B0 |
C0 |
D0 |
1 |
A1 |
B1 |
C1 |
D1 |
2 |
A2 |
B2 |
C2 |
D2 |
3 |
A3 |
B3 |
C3 |
D3 |
3 |
A4 |
B4 |
C4 |
D4 |
5 |
A5 |
B5 |
C5 |
D5 |
6 |
A6 |
B6 |
C6 |
D6 |
7 |
A7 |
B7 |
C7 |
D7 |
8 |
A8 |
B8 |
C8 |
D8 |
9 |
A9 |
B9 |
C9 |
D9 |
10 |
A10 |
B10 |
C10 |
D10 |
11 |
A11 |
B11 |
C11 |
D11 |
- 索引可以重复 。无非就是合并后,搜索的时候。你搜索3它出来两条
all_classes = pd.concat(
[df1, df2, df3],
keys=["x", "y", "z"])
all_classes
|
|
A |
B |
C |
D |
x |
0 |
A0 |
B0 |
C0 |
D0 |
1 |
A1 |
B1 |
C1 |
D1 |
2 |
A2 |
B2 |
C2 |
D2 |
3 |
A3 |
B3 |
C3 |
D3 |
y |
3 |
A4 |
B4 |
C4 |
D4 |
5 |
A5 |
B5 |
C5 |
D5 |
6 |
A6 |
B6 |
C6 |
D6 |
7 |
A7 |
B7 |
C7 |
D7 |
z |
8 |
A8 |
B8 |
C8 |
D8 |
9 |
A9 |
B9 |
C9 |
D9 |
10 |
A10 |
B10 |
C10 |
D10 |
11 |
A11 |
B11 |
C11 |
D11 |
key
来加了一层按表来的索引。 有时候比如想知道是哪个数据的,可以加。
- 注意:这层检索可以重复,建表时没有问题,但是检索的时候会出现问题,可以自己试试
all_classes.loc["x"]
|
A |
B |
C |
D |
0 |
A0 |
B0 |
C0 |
D0 |
1 |
A1 |
B1 |
C1 |
D1 |
2 |
A2 |
B2 |
C2 |
D2 |
3 |
A3 |
B3 |
C3 |
D3 |
- 【左右拼接】:
axis=1
df1 = pd.DataFrame({
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
}, index=[0, 1, 2, 3],)
df4 = pd.DataFrame({
"B": ["B2", "B3", "B6", "B7"],
"D": ["D2", "D3", "D6", "D7"],
"F": ["F2", "F3", "F6", "F7"],
}, index=[2, 3, 6, 7],)
pd.concat([df1, df4], axis=1)
|
A |
B |
C |
D |
B |
D |
F |
0 |
A0 |
B0 |
C0 |
D0 |
NaN |
NaN |
NaN |
1 |
A1 |
B1 |
C1 |
D1 |
NaN |
NaN |
NaN |
2 |
A2 |
B2 |
C2 |
D2 |
B2 |
D2 |
F2 |
3 |
A3 |
B3 |
C3 |
D3 |
B3 |
D3 |
F3 |
6 |
NaN |
NaN |
NaN |
NaN |
B6 |
D6 |
F6 |
7 |
NaN |
NaN |
NaN |
NaN |
B7 |
D7 |
F7 |
- 拼接的时候 pandas 会自动将缺失的部分填充成 NaN
- 默认是外连接join=“outer”;也可以改成join="inner"表示内连接,只显示都拥有的的
pd.concat([df1, df4], axis=1, join="inner")
|
A |
B |
C |
D |
B |
D |
F |
2 |
A2 |
B2 |
C2 |
D2 |
B2 |
D2 |
F2 |
3 |
A3 |
B3 |
C3 |
D3 |
B3 |
D3 |
F3 |
3. 【忽略以前的index用全新的索引用】:`ignore_index=Ture`
- 注意,这里忽略索索引 ==主要是上下拼接的方式==
pd.concat(
[df1, df4],
ignore_index=True,
sort=False)
|
A |
B |
C |
D |
F |
0 |
A0 |
B0 |
C0 |
D0 |
NaN |
1 |
A1 |
B1 |
C1 |
D1 |
NaN |
2 |
A2 |
B2 |
C2 |
D2 |
NaN |
3 |
A3 |
B3 |
C3 |
D3 |
NaN |
4 |
NaN |
B2 |
NaN |
D2 |
F2 |
5 |
NaN |
B3 |
NaN |
D3 |
F3 |
6 |
NaN |
B6 |
NaN |
D6 |
F6 |
7 |
NaN |
B7 |
NaN |
D7 |
F7 |
- 【DataFrame拼接Series】
new_col = pd.Series(
["X0", "X1", "X2", "X3"], name="X")
pd.concat([df1, new_col], axis=1)
|
A |
B |
C |
D |
X |
0 |
A0 |
B0 |
C0 |
D0 |
X0 |
1 |
A1 |
B1 |
C1 |
D1 |
X1 |
2 |
A2 |
B2 |
C2 |
D2 |
X2 |
3 |
A3 |
B3 |
C3 |
D3 |
X3 |
- 列方向上拼接:
-
- 方法1:因为Series是列形式;所以要
.to_frame().T
new_row = pd.Series(
["X0", "X1", "X2", "X3"],
index=["A", "B", "C", "E"])
pd.concat(
[df1, new_row.to_frame().T],
ignore_index=True)
df1.append(new_row, ignore_index=True)
|
A |
B |
C |
D |
E |
0 |
A0 |
B0 |
C0 |
D0 |
NaN |
1 |
A1 |
B1 |
C1 |
D1 |
NaN |
2 |
A2 |
B2 |
C2 |
D2 |
NaN |
3 |
A3 |
B3 |
C3 |
D3 |
NaN |
4 |
X0 |
X1 |
X2 |
NaN |
X3 |
16.2.2 融合Merge
concat
可以一次性合并多个 df,可以【左右】,也可以【上下】拼接
merge
是用来针对两张 df 做【左右】拼接的。
- 【拼接】:
pd.merge()
,通过什么为标准拼接用on
left = pd.DataFrame({
"key": ["K0", "K1", "K2", "K3"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
})
right = pd.DataFrame({
"key": ["K0", "K1", "K2", "K4"],
"B": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
})
pd.merge(left, right, on="key")
|
key |
A |
B_x |
B_y |
D |
0 |
K0 |
A0 |
B0 |
C0 |
D0 |
1 |
K1 |
A1 |
B1 |
C1 |
D1 |
2 |
K2 |
A2 |
B2 |
C2 |
D2 |
- 【双拼】
left = pd.DataFrame({
"key1": ["K0", "K0", "K1", "K2"],
"key2": ["K0", "K1", "K0", "K1"],
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
})
right = pd.DataFrame({
"key1": ["K0", "K1", "K1", "K2"],
"key2": ["K0", "K0", "K0", "K0"],
"C": ["C0", "C1", "C2", "C3"],
"D": ["D0", "D1", "D2", "D3"],
})
pd.merge(left, right, on=["key1", "key2"])
|
key1 |
key2 |
A |
B |
C |
D |
0 |
K0 |
K0 |
A0 |
B0 |
C0 |
D0 |
1 |
K1 |
K0 |
A2 |
B2 |
C1 |
D1 |
2 |
K1 |
K0 |
A2 |
B2 |
C2 |
D2 |
- 【其他拼接方式】:
how=
outer
: 集合两个 df 所有 的 key
inner
: 集合两个 df 同时拥有 的 key
left
: 仅考虑左边 df 所有 的 key
right
: 仅考虑右边 df 所有 的 key
cross
: 对于两个 df key 的笛卡尔积
pd.merge(left, right, how="left", on=["key1", "key2"])
|
key1 |
key2 |
A |
B |
C |
D |
0 |
K0 |
K0 |
A0 |
B0 |
C0 |
D0 |
1 |
K0 |
K1 |
A1 |
B1 |
NaN |
NaN |
2 |
K1 |
K0 |
A2 |
B2 |
C1 |
D1 |
3 |
K1 |
K0 |
A2 |
B2 |
C2 |
D2 |
4 |
K2 |
K1 |
A3 |
B3 |
NaN |
NaN |
*其他方法类似
16.2.3 接入Join
- merge() 是基于给定的某个 on=“key” 来拼接
- join 其实是 df.join()。可以和 concat() 一样,都是 index,也可以像 merge() 带一个 on=“key” 去使用一个 column 作为索引。
- 【类似于concat】:用
how
。默认是使用how="left"
的;还可以 ‘right’, ‘outer’, ‘inner’
left = pd.DataFrame({
"A": ["A0", "A1", "A2"],
"B": ["B0", "B1", "B2"]
}, index=["K0", "K1", "K2"])
right = pd.DataFrame({
"C": ["C0", "C2", "C3"],
"D": ["D0", "D2", "D3"]
}, index=["K0", "K2", "K3"])
left.join(right,how='inner')
|
A |
B |
C |
D |
K0 |
A0 |
B0 |
C0 |
D0 |
K2 |
A2 |
B2 |
C2 |
D2 |
- 【类似于merge】:用
on
。
left = pd.DataFrame({
"A": ["A0", "A1", "A2", "A3"],
"B": ["B0", "B1", "B2", "B3"],
"key": ["K0", "K1", "K0", "K1"],
})
right = pd.DataFrame({
"C": ["C0", "C1"],
"D": ["D0", "D1"]
}, index=["K0", "K1"])
left.join(right, on="key")
|
A |
B |
key |
C |
D |
0 |
A0 |
B0 |
K0 |
C0 |
D0 |
1 |
A1 |
B1 |
K1 |
C1 |
D1 |
2 |
A2 |
B2 |
K0 |
C0 |
D0 |
3 |
A3 |
B3 |
K1 |
C1 |
D1 |