python - 将多索引 daframe 与系列连接起来
问题描述
我有一个多索引数据框,其中包含用于训练机器学习模型的功能。
X_train
win -1 0 1
res A B A B A B
id pos
foo 0 0.1 0.2 0.3 0.1 0.5 0.6
1 0.3 0.7 0.2 0.1 0.4 0.6
2 0.1 0.2 0.3 0.1 0.5 0.6
bar 0 0.1 0.0 0.3 0.1 0.5 0.6
1 0.1 0.2 0.0 0.3 0.9 0.6
2 0.1 0.2 0.3 0.1 0.5 0.6
以及带有类标签的熊猫系列(或数据框)
y_train
id pos
foo 0 0
1 2
2 1
bar 0 0
1 0
2 1
Name: Class
我想连接它们并获得
full_train
win -1 0 1 Class
res A B A B A B
id pos
foo 0 0.1 0.2 0.3 0.1 0.5 0.6 0
1 0.3 0.7 0.2 0.1 0.4 0.6 2
2 0.1 0.2 0.3 0.1 0.5 0.6 1
bar 0 0.1 0.0 0.3 0.1 0.5 0.6 0
1 0.1 0.2 0.0 0.3 0.9 0.6 0
2 0.1 0.2 0.3 0.1 0.5 0.6 1
但如果我这样做full_train = pd.concat([X_train, y_train], axis=1)
,我会获得:
(-1,A)(-1,B)(0,A) (0,B)(1,A) (1,B) Class
id pos
foo 0 0.1 0.2 0.3 0.1 0.5 0.6 0
1 0.3 0.7 0.2 0.1 0.4 0.6 2
2 0.1 0.2 0.3 0.1 0.5 0.6 1
bar 0 0.1 0.0 0.3 0.1 0.5 0.6 0
1 0.1 0.2 0.0 0.3 0.9 0.6 0
2 0.1 0.2 0.3 0.1 0.5 0.6 1
是否有可能获得我的预期输出?Pandas 是否支持这种混合列既是多索引又是单索引?
解决方案
熊猫确实支持这个!但是,您需要了解一些隐藏知识以进行连接以使其按预期工作。
对于以下示例,我将使用此数据框和此系列y_train
:
import pandas as pd
import numpy as np
columns = pd.MultiIndex.from_product([[-1, 0, 1], ["A", "B"]], names=["win", "res"])
index = pd.MultiIndex.from_product([["foo", "bar"], [0, 1, 2]], names=["id", "pos"])
m = len(columns)
n = len(index)
data = np.random.randint(5, size=(m * n)).reshape(m, n)
df = pd.DataFrame(data, index=index, columns=columns)
print(df)
win -1 0 1
res A B A B A B
id pos
foo 0 3 4 4 4 4 1
1 4 1 4 3 1 0
2 0 4 2 2 3 2
bar 0 3 2 1 4 1 1
1 0 3 1 1 0 3
2 2 0 2 1 0 1
标签:
y_train = pd.Series(np.random.randint(3, size=m), index=index, name="class")
print(y_train)
id pos
foo 0 2
1 1
2 2
bar 0 1
1 1
2 2
Name: class, dtype: int32
如果您y_train
是系列,则根本不需要使用concat
。最直接的方法是将您的y_train
系列简单地分配到原始数据框中。
new_df = df.copy() # preserving original dataframe for use in later examples
new_df["class"] = y_train
print(new_df)
win -1 0 1 class
res A B A B A B
id pos
foo 0 3 4 4 4 4 1 2
1 4 1 4 3 1 0 1
2 0 4 2 2 3 2 2
bar 0 3 2 1 4 1 1 1
1 0 3 1 1 0 3 1
2 2 0 2 1 0 1 2
# We can select our "class" column and get its `Series` out via:
print(new_df["class"])
id pos
foo 0 2
1 1
2 2
bar 0 1
1 1
2 2
Name: class, dtype: int32
# Then to access our other columns, we'll need to supply a key as a tuple:
print(new_df[(-1, "A")])
id pos
foo 0 4
1 1
2 4
bar 0 2
1 3
2 0
Name: (-1, B), dtype: int32
y_train
如果你是一个数据框而不是一个系列,现在事情会变得有点棘手。但是,这种方法也可以解决您的concat
问题。您需要做的就是将标签数据框的 ( y_train
) 列索引替换为MultiIndex
与您尝试连接的其他数据框具有相同级别数的索引。您需要使用空级别来实现这一点(空级别是唯一值是空字符串的级别。NOT None 或 NaN)
new_ytrain = y_train.to_frame() # promote y_train to a dataframe
# In order to feed this into concat, we'll need to give our dataframe a columnar multiindex
# This multiindex essentially has an empty second level
new_ytrain.columns = pd.MultiIndex.from_product([new_ytrain.columns, [""]])
print(new_ytrain)
class
id pos
foo 0 2
1 1
2 2
bar 0 1
1 1
2 2
在我们的y_train
数据框表示中,您会看到我们的列标题和实际数据之间有一个空格。这代表我们插入的空级别。现在我们的原始数据框和我们y_train
都有一个MultiIndex
具有 2 个级别的列,我们可以按预期使用 concat 没有问题:
out = pd.concat([df, new_ytrain], axis=1)
print(out)
win -1 0 1 class
res A B A B A B
id pos
foo 0 3 4 4 4 4 1 2
1 4 1 4 3 1 0 1
2 0 4 2 2 3 2 2
bar 0 3 2 1 4 1 1 1
1 0 3 1 1 0 3 1
2 2 0 2 1 0 1 2
与分配方法一样,我们可以轻松地在此数据框中选择我们的“类”列。
print(out["class"])
id pos
foo 0 2
1 1
2 2
bar 0 1
1 1
2 2
Name: class, dtype: int32
推荐阅读
- maven - MAVEN:无法检索插件描述符 [错误]
- vb.net - 按文件类型将多个文件加载到 ListView 控件中
- c - VS2019:包含文件作为项目宏
- python - 带有蓝牙扬声器的python项目
- google-apps-script - 如何使用 Google Script 将 JOIN 和 FILTER 公式应用于 Google 表格中的整个列?
- python - 在 python 中使用 .replace() 来避免如下错误
- json - Swift JSON 验证无法通过我的 web api 获取这些数据,我不知道为什么
- javascript - 我收到一个错误“';' expected.ts(1005)" 甚至不使用 TS?
- c - 为什么int返回类型函数可以返回字符串?
- google-sheets - ArrayFormula 不正确地显示日期。我怎样才能解决这个问题?