【问题标题】:Mapping pandas dataframe by condition按条件映射熊猫数据框
【发布时间】:2021-08-05 16:11:32
【问题描述】:

我正在尝试编写一个在 2 个数据帧之间映射并根据条件返回值的函数。一种是映射 DF,如下所示。

data1 = {'variable':['A','A','A','B','B','C','C'],
    'lower' : [0,100,200,0,5,1,4],
    'upper' : [100,200,300,5,10,4,8],
    'value' : [32,15,45,18,46,33,45]}

df1 = pd.DataFrame(data1, columns = ['variable','lower', 'upper','value'])

print(df1)

另一个是我将应用映射的 DF,如下所示。

data2 = {'A':[23,244,131,54,258,117,43,224],
    'B' : [0,2,1,9,7,4,6,3],
    'C' : [2,1,7,4,8,3,8,1]}

df2 = pd.DataFrame(data2, columns = ['A','B', 'C'])

print(df2)

我要做的是创建新列mapped_A,它将检查DF 的所有行与A 的映射,并根据上限和下限返回值。例如mapped_A 列的第一行将是32,因为0 < 23 <= 100。与列 BC 相同。

期望的输出:

我可以对逻辑进行硬编码,如下所示,但必须有更好的方法来处理。

conditions = [(df2['A'] > 0) & (df2['A'] <= 100),
              (df2['A'] > 100) & (df2['A'] <= 200),
              (df2['A'] > 200) & (df2['A'] <= 300)]
choices = [32, 15, 45]

df2['mapped_A'] = np.select(conditions, choices, default='null')

【问题讨论】:

  • BC 列的预期输出错误。

标签: python pandas dataframe


【解决方案1】:

好吧,我认为 ThePyGuy 的解决方案更加优雅,但您可以创建一个自定义函数来节省复制和粘贴,如下所示:

def maps2(d1, d2):
    out = {}
    for i in d2:
        condNums = [n for n in range(len(d1["variable"])) if d1["variable"][n] == i]
        n = "mapped_" + i
        out[n] = []
        for u in range(len(d2[i])):
            for o in condNums:
                if d2[i][u] >= d1["lower"][o] and d2[i][u] <= d1["upper"][o]:
                    out[n].append(d1["value"][o])

    return out

我还更改了if 中的逻辑条件,因为您需要的输出与您的原始逻辑有冲突(&gt; 现在是&gt;=)。

【讨论】:

    【解决方案2】:

    尽管通常不建议使用eval,但在必须动态构建多个条件的情况下使用它还是很方便的。您可以构建创建这些掩码所需的字符串,然后在使用 np.select 时将其传递给内置的 eval,迭代第二个数据帧中的每一列,并将值分配给一个新列。

    for col in df2:
        colValues = df1[df1['variable'].eq(col)]
        condition = '['+\
                    ','.join(colValues.apply(lambda x:f"(df2[col]>{x['lower']}) & (df2[col]<={x['upper']})", 
                                             axis=1).values)+\
                    ']'
        values = colValues['value']
        df2[f'maped_{col}'] = np.select(eval(condition), values, default=np.nan)
    

    输出:

         A  B  C  maped_A  maped_B  maped_C
    0   23  0  2     32.0      NaN     33.0
    1  244  2  1     45.0     18.0      NaN
    2  131  1  7     15.0     18.0     45.0
    3   54  9  4     32.0     46.0     33.0
    4  258  7  8     45.0     46.0     45.0
    5  117  4  3     15.0     18.0     33.0
    6   43  6  8     32.0     46.0     45.0
    7  224  3  1     45.0     18.0      NaN
    

    【讨论】:

      猜你喜欢
      • 2016-12-30
      • 2017-05-08
      • 2018-07-16
      • 1970-01-01
      • 2022-11-18
      • 2019-05-15
      • 2018-06-03
      • 2016-09-12
      • 1970-01-01
      相关资源
      最近更新 更多