3

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

  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() 之类的东西时,我似乎永远无法访问所需的所有三件事(值、索引和列名)......有没有一种有效的方法来实现预期的结果?非常感谢!

4

1 回答 1

2

DataFrame使用from 列表创建MultiIndex,然后比较 by DataFrame.lt,对于每个级别使用 select DataFrame.xs,更改索引 byDataFrame.reindex_like并通过 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
于 2019-07-28T05:54:13.570 回答