如何使用 Pandas 将多索引系列连接到单个索引数据框?
How to join a multi-index series to a single index dataframe with Pandas?
考虑以下单索引 DataFrame:
energy fat
1 2000 28
2 1900 17
3 2200 30
4 1750 15
5 1800 18
6 1600 12
我也有一个多索引系列:
1 vitamin-c 0.0004
vitamin-a 0.0150
2 vitamin-c 0.0030
3 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4 vitamin-a 0.0780
5 vitamin-b 0.9650
6 vitamin-e 1.9801
vitamin-c 1.0011
我怎样才能加入这两个结果如下所示:
energy fat vitamins
1 2000 28 vitamin-c 0.0004
vitamin-a 0.0150
2 1900 17 vitamin-c 0.0030
3 2200 30 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4 1750 15 vitamin-a 0.0780
5 1800 18 vitamin-b 0.9650
6 1600 12 vitamin-e 1.9801
vitamin-c 1.0011
我尝试了 df.join(series, how = 'inner')
但我得到的只是以下错误消息:
"ValueError: cannot join with no level specified and no overlapping names"
有人可以解释一下我在这里做错了什么以及我如何才能实现两者的结合吗?谢谢!
源集:
In [96]: s
Out[96]:
id vitamins
1.0 vitamin-c 0.0004
vitamin-a 0.0150
2.0 vitamin-c 0.0030
3.0 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4.0 vitamin-a 0.0780
5.0 vitamin-b 0.9650
6.0 vitamin-e 1.9801
vitamin-c 1.0011
Name: val, dtype: float64
In [97]: df
Out[97]:
energy fat
1 2000 28
2 1900 17
3 2200 30
4 1750 15
5 1800 18
6 1600 12
解决方案:
In [99]: s.reset_index() \
.merge(df, left_on='id', right_index=True) \
.set_index(['id','energy','fat','vitamins'])
Out[99]:
val
id energy fat vitamins
1.0 2000 28 vitamin-c 0.0004
vitamin-a 0.0150
2.0 1900 17 vitamin-c 0.0030
3.0 2200 30 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4.0 1750 15 vitamin-a 0.0780
5.0 1800 18 vitamin-b 0.9650
6.0 1600 12 vitamin-e 1.9801
vitamin-c 1.0011
选项 1
我不建议将不应该存在的内容移动到索引中。
也就是说,如果您的索引级别被适当命名,您可以使用 pd.DataFrame.join
,或者更确切地说它们匹配,因此 pandas 知道要加入什么。
df.rename_axis('ord').join(s.rename_axis(['ord', 'vit']).rename('val'))
energy fat val
ord vit
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
多写几行以增加可读性
s = s.rename_axis(['ord', 'vit']).rename('val')
df = df.rename_axis('ord')
df.join(s)
energy fat val
ord vit
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
选项 2
我们还可以将 pd.concat
与 loc
和 pd.Index.get_level_values
一起使用
pd.concat(
[df.loc[s.index.get_level_values(0)].set_index(s.index), s.rename('val')],
axis=1
)
energy fat val
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
如果您将名称添加到 index/multiindex,您可以使用连接:
In [11]: df
Out[11]:
energy fat
n
1 2000 28
2 1900 17
3 2200 30
4 1750 15
5 1800 18
6 1600 12
In [12]: df2
Out[12]:
val
n vitamin
1 vitamin-c 0.0004
vitamin-a 0.0150
2 vitamin-c 0.0030
3 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4 vitamin-a 0.0780
5 vitamin-b 0.9650
6 vitamin-e 1.9801
vitamin-c 1.0011
In [13]: df.join(df2)
Out[13]:
energy fat val
n vitamin
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
注意:通过设置 .index.names:
In [21]: df.index.names = ["n"] # or .name = "n"
In [22]: df2.index.names = ["n", "vitamin"]
考虑以下单索引 DataFrame:
energy fat
1 2000 28
2 1900 17
3 2200 30
4 1750 15
5 1800 18
6 1600 12
我也有一个多索引系列:
1 vitamin-c 0.0004
vitamin-a 0.0150
2 vitamin-c 0.0030
3 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4 vitamin-a 0.0780
5 vitamin-b 0.9650
6 vitamin-e 1.9801
vitamin-c 1.0011
我怎样才能加入这两个结果如下所示:
energy fat vitamins
1 2000 28 vitamin-c 0.0004
vitamin-a 0.0150
2 1900 17 vitamin-c 0.0030
3 2200 30 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4 1750 15 vitamin-a 0.0780
5 1800 18 vitamin-b 0.9650
6 1600 12 vitamin-e 1.9801
vitamin-c 1.0011
我尝试了 df.join(series, how = 'inner')
但我得到的只是以下错误消息:
"ValueError: cannot join with no level specified and no overlapping names"
有人可以解释一下我在这里做错了什么以及我如何才能实现两者的结合吗?谢谢!
源集:
In [96]: s
Out[96]:
id vitamins
1.0 vitamin-c 0.0004
vitamin-a 0.0150
2.0 vitamin-c 0.0030
3.0 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4.0 vitamin-a 0.0780
5.0 vitamin-b 0.9650
6.0 vitamin-e 1.9801
vitamin-c 1.0011
Name: val, dtype: float64
In [97]: df
Out[97]:
energy fat
1 2000 28
2 1900 17
3 2200 30
4 1750 15
5 1800 18
6 1600 12
解决方案:
In [99]: s.reset_index() \
.merge(df, left_on='id', right_index=True) \
.set_index(['id','energy','fat','vitamins'])
Out[99]:
val
id energy fat vitamins
1.0 2000 28 vitamin-c 0.0004
vitamin-a 0.0150
2.0 1900 17 vitamin-c 0.0030
3.0 2200 30 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4.0 1750 15 vitamin-a 0.0780
5.0 1800 18 vitamin-b 0.9650
6.0 1600 12 vitamin-e 1.9801
vitamin-c 1.0011
选项 1
我不建议将不应该存在的内容移动到索引中。
也就是说,如果您的索引级别被适当命名,您可以使用 pd.DataFrame.join
,或者更确切地说它们匹配,因此 pandas 知道要加入什么。
df.rename_axis('ord').join(s.rename_axis(['ord', 'vit']).rename('val'))
energy fat val
ord vit
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
多写几行以增加可读性
s = s.rename_axis(['ord', 'vit']).rename('val')
df = df.rename_axis('ord')
df.join(s)
energy fat val
ord vit
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
选项 2
我们还可以将 pd.concat
与 loc
和 pd.Index.get_level_values
pd.concat(
[df.loc[s.index.get_level_values(0)].set_index(s.index), s.rename('val')],
axis=1
)
energy fat val
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
如果您将名称添加到 index/multiindex,您可以使用连接:
In [11]: df
Out[11]:
energy fat
n
1 2000 28
2 1900 17
3 2200 30
4 1750 15
5 1800 18
6 1600 12
In [12]: df2
Out[12]:
val
n vitamin
1 vitamin-c 0.0004
vitamin-a 0.0150
2 vitamin-c 0.0030
3 vitamin-d 1.2000
vitamin-e 1.0007
vitamin-c 1.2020
4 vitamin-a 0.0780
5 vitamin-b 0.9650
6 vitamin-e 1.9801
vitamin-c 1.0011
In [13]: df.join(df2)
Out[13]:
energy fat val
n vitamin
1 vitamin-c 2000 28 0.0004
vitamin-a 2000 28 0.0150
2 vitamin-c 1900 17 0.0030
3 vitamin-d 2200 30 1.2000
vitamin-e 2200 30 1.0007
vitamin-c 2200 30 1.2020
4 vitamin-a 1750 15 0.0780
5 vitamin-b 1800 18 0.9650
6 vitamin-e 1600 12 1.9801
vitamin-c 1600 12 1.0011
注意:通过设置 .index.names:
In [21]: df.index.names = ["n"] # or .name = "n"
In [22]: df2.index.names = ["n", "vitamin"]