根据索引、列名和原始值映射 Pandas 数据框?

Map Pandas dataframe based on index, column name and original value?

我想将数据帧的值映射到不同数据帧的值(也可能是字典)。 我要映射到的元素取决于三件事:

  1. 原值,
  2. 索引名称和
  3. 列名称。

例如我有以下数据框

df = pd.DataFrame(
    data={"Feature_1": [-1, 1, 1, 3], "Feature_2": [0, 2, 2, 4]},
    index=["00-1", "00-1", "00-2", "00-2"],
)

看起来像这样:

      Feature_1  Feature_2
00-1         -1          0
00-1          1          2
00-2          1          2
00-2          3          4

还有另一个名为 mapping 的数据框,其中包含映射规则:

dict_01 = {"00-1": {"Feature_1": [0, "A", "B"], "Feature_2": [1, "C", "D"]},
           "00-2": {"Feature_1": [2, "E", "F"], "Feature_2": [3, "G", "H"]}}
mapping = pd.DataFrame.from_dict(dict_01).transpose()

因此,映射如下所示:

      Feature_1  Feature_2
00-1  [0, A, B]  [1, C, D]
00-2  [2, E, F]  [3, G, H]

我想根据某个阈值将每个元素映射到两个值之一。所有索引特征组合的阈值都不同。 在映射数据框中,每个列表的第一个元素代表阈值。 如果原始值小于此阈值,则应将其映射到列表的第二个元素。 如果大于等于,则映射到第三个元素。

我可以通过遍历行和列(见下文)来获得所需的结果。

df_mapped = df.copy()
for col in df_mapped.columns:
    for row in range(len(df_mapped)):
        idx = df_mapped.index[row]
        if df_mapped[col].iloc[row] < mapping[col].loc[idx][0]:
            df_mapped[col].iloc[row] = mapping[col].loc[idx][1]
        else:
            df_mapped[col].iloc[row] = mapping[col].loc[idx][2]

结果(df_mapped):

     Feature_1 Feature_2
00-1         A         C
00-1         B         D
00-2         E         G
00-2         F         H

但实际数据集在两个维度(行和列)上都很大,我正在寻找一种有效的方法来计算它。 当使用 apply() 或 map() 之类的东西时,我似乎永远无法访问所需的所有三样东西(值、索引和列名)... 有没有一种有效的方法来达到预期的结果? 非常感谢!

从列表中用 MultiIndex 创建 DataFrame,然后用 DataFrame.lt, for select by each level use DataFrame.xs, change index by DataFrame.reindex_like and set values by mask by DataFrame.where:

进行比较
comp = [pd.DataFrame(mapping[x].values.tolist(), index=mapping.index) for x in mapping.columns]
mapping1 = pd.concat(comp, axis=1, keys=mapping.columns)
print (mapping1)
     Feature_1       Feature_2      
             0  1  2         0  1  2
00-1         0  A  B         1  C  D
00-2         2  E  F         3  G  H

mask = df.lt(mapping1.xs(0, level=1, axis=1))
df1 = (mapping1.xs(1, level=1, axis=1)
               .reindex_like(df)
               .where(mask, mapping1.xs(2, level=1, axis=1)))
print (df1)
     Feature_1 Feature_2
00-1         A         C
00-1         B         D
00-2         E         G
00-2         F         H