Pandas转换连接详解

目录
拼接
1.1 append
1.2 concat
关联
2.1 merge
2.2 join

更多:Pandas

# 导入相关库
import numpy as np
import pandas as pd

拼接

有两个DataFrame,都存储了用户的一些信息,现在要拼接起来,组成一个DataFrame,如何实现呢?

data1 = {
    "name": ["Tom", "Bob"],
    "age": [18, 30],
    "city": ["Bei Jing ", "Shang Hai "]
}
df1 = pd.DataFrame(data=data1)
df1

agecityname
018Bei JingTom
130Shang HaiBob
data2 = {
    "name": ["Mary", "James"],
    "age": [35, 18],
    "city": ["Guang Zhou", "Shen Zhen"]
}
df2 = pd.DataFrame(data=data2)
df2

agecityname
035Guang ZhouMary
118Shen ZhenJames
append

append 是最简单的拼接两个DataFrame的方法。

df1.append(df2)

agecityname
018Bei JingTom
130Shang HaiBob
035Guang ZhouMary
118Shen ZhenJames

可以看到,拼接后的索引默认还是原有的索引,如果想要重新生成索引的话,设置参数 ignore_index=True 即可。

df1.append(df2, ignore_index=True)

agecityname
018Bei JingTom
130Shang HaiBob
235Guang ZhouMary
318Shen ZhenJames

concat

除了 append 这种方式之外,还有 concat 这种方式可以实现相同的功能。

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

agecityname
018Bei JingTom
130Shang HaiBob
235Guang ZhouMary
318Shen ZhenJames

如果想要区分出不同的DataFrame的数据,可以通过设置参数 keys,当然得设置参数 ignore_index=False

pd.concat(objs, ignore_index=False, keys=["df1", "df2"])


agecityname
df1018Bei JingTom
130Shang HaiBob
df2035Guang ZhouMary
118Shen ZhenJames
关联

有两个DataFrame,分别存储了用户的部分信息,现在需要将用户的这些信息关联起来,如何实现呢?

data1 = {
    "name": ["Tom", "Bob", "Mary", "James"],
    "age": [18, 30, 35, 18],
    "city": ["Bei Jing ", "Shang Hai ", "Guang Zhou", "Shen Zhen"]
}
df1 = pd.DataFrame(data=data1)
df1

agecityname
018Bei JingTom
130Shang HaiBob
235Guang ZhouMary
318Shen ZhenJames
data2 = {"name": ["Bob", "Mary", "James", "Andy"],
        "sex": ["male", "female", "male", np.nan],
         "income": [8000, 8000, 4000, 6000]
}
df2 = pd.DataFrame(data=data2)
df2

incomenamesex
08000Bobmale
18000Maryfemale
24000Jamesmale
36000AndyNaN

merge

通过 pd.merge 可以关联两个DataFrame,这里我们设置参数 on="name",表示依据 name 来作为关联键。

pd.merge(df1, df2, on="name")

agecitynameincomesex
030Shang HaiBob8000male
135Guang ZhouMary8000female
218Shen ZhenJames4000male

关联后发现数据变少了,只有 3 行数据,这是因为默认关联的方式是 inner,如果不想丢失任何数据,可以设置参数 how="outer"

pd.merge(df1, df2, on="name", how="outer")

agecitynameincomesex
018.0Bei JingTomNaNNaN
130.0Shang HaiBob8000.0male
235.0Guang ZhouMary8000.0female
318.0Shen ZhenJames4000.0male
4NaNNaNAndy6000.0NaN

可以看到,设置参数 how=”outer” 后,确实不会丢失任何数据,他会在不存在的地方填为缺失值。

如果我们想保留左边所有的数据,可以设置参数 how="left";反之,如果想保留右边的所有数据,可以设置参数 how="right"

pd.merge(df1, df2, on="name", how="left")

agecitynameincomesex
018Bei JingTomNaNNaN
130Shang HaiBob8000.0male
235Guang ZhouMary8000.0female
318Shen ZhenJames4000.0male

有时候,两个 DataFrame 中需要关联的键的名称不一样,可以通过 left_on 和 right_on 来分别设置。

df1.rename(columns={"name": "name1"}, inplace=True)
df1

agecityname1
018Bei JingTom
130Shang HaiBob
235Guang ZhouMary
318Shen ZhenJames
df2.rename(columns={"name": "name2"}, inplace=True)
df2

incomename2sex
08000Bobmale
18000Maryfemale
24000Jamesmale
36000AndyNaN
pd.merge(df1, df2, left_on="name1", right_on="name2")

agecityname1incomename2sex
030Shang HaiBob8000Bobmale
135Guang ZhouMary8000Maryfemale
218Shen ZhenJames4000Jamesmale

有时候,两个DataFrame中都包含相同名称的字段,如何处理呢?

我们可以设置参数 suffixes,默认 suffixes=('_x', '_y') 表示将相同名称的左边的DataFrame的字段名加上后缀 _x,右边加上后缀 _y

df1["sex"] = "male"
df1

agecityname1sex
018Bei JingTommale
130Shang HaiBobmale
235Guang ZhouMarymale
318Shen ZhenJamesmale
pd.merge(df1, df2, left_on="name1", right_on="name2")

agecityname1sex_xincomename2sex_y
030Shang HaiBobmale8000Bobmale
135Guang ZhouMarymale8000Maryfemale
218Shen ZhenJamesmale4000Jamesmale
pd.merge(df1, df2, left_on="name1", right_on="name2", suffixes=("_left", "_right"))

agecityname1sex_leftincomename2sex_right
030Shang HaiBobmale8000Bobmale
135Guang ZhouMarymale8000Maryfemale
218Shen ZhenJamesmale4000Jamesmale
join

除了 merge 这种方式外,还可以通过 join 这种方式实现关联。相比 mergejoin 这种方式有以下几个不同:

  • 默认参数on=None,表示关联时使用左边和右边的索引作为键,设置参数on可以指定的是关联时左边的所用到的键名
  • 左边和右边字段名称重复时,通过设置参数 lsuffix 和 rsuffix 来解决。
df1.join(df2.set_index("name2"), on="name1", lsuffix="_left")

agecityname1sex_leftincomesex
018Bei JingTommaleNaNNaN
130Shang HaiBobmale8000.0male
235Guang ZhouMarymale8000.0female
318Shen ZhenJamesmale4000.0male

发表评论

电子邮件地址不会被公开。 必填项已用*标注