首页 > 解决方案 > 使用 Pandas 中的字典从两列创建新列

问题描述

我想为分组列的每一组创建一个基于组和阈值的列,以便从另一列截断。

数据框如下:

     df_in -> 

       unique_id  myvalue identif
   0      CTA15   19.0     TOP
   1      CTA15   22.0     TOP
   2      CTA15   28.0     TOP
   3      CTA15   18.0     TOP
   4      CTA15   22.4     TOP
   5      AC007    2.0     TOP
   6      AC007    2.3    SDME
   7      AC007    2.0    SDME
   8      AC007    5.0    SDME
   9      AC007    3.0    SDME
   10     AC007   31.4    SDME
   11     AC007    4.4    SDME
   12      CGT6    9.7    BTME
   13      CGT6   44.5    BTME
   14      TVF5    6.7    BTME
   15      TVF5    9.1    BTME
   16      TVF5   10.0    BTME
   17      BGD1    1.0    BTME
   18      BGD1    1.6     NON
   19       GHB   51.0     NON
   20       GHB   54.0     NON
   21       GHB    4.7     NON

所以我创建了一个基于“identif”列的每一组的字典:

    md = {'TOP': 22, 'SDME': 10, 'BTME': 20, 'NON':20}

所以我的目标是根据以下条件创建一个新列,比如“chk”:

如果“identif”列与字典“md”中的键匹配,并且该键的值大于“myvalue”列中的相应值,那么我将得到 1,否则为 0。

但是,我正在尝试找到一种使用 map/groupby/apply 创建新输出数据框的好方法。我现在正在使用如下函数做一个非常低效的方法(这在百万行的真实数据上花费了大量时间):

 def myfilter(df, idCol, valCol, mydict):

   for index,row in df.iterrows():
      for key, value in mydict.items(): 
         if row[idCol] == key and row[valCol] >= value:
             df['chk'] = 1
         elif row[idCol] == key and row[valCol] < value:
             df['chk'] = 0

  return df

通过以下调用获取输出:

     df_out = myfilter(df_in, 'identif', 'myvalue', md)

所以我的输出将是:

     df_out ->

         unique_id  myvalue identif  chk
    0      CTA15     19.0     TOP    0
    1      CTA15     22.0     TOP    1
    2      CTA15     28.0     TOP    1
    3      CTA15     18.0     TOP    0
    4      CTA15     22.4     TOP    1
    5      AC007      2.0     TOP    0
    6      AC007      2.3    SDME    0
    7      AC007      2.0    SDME    0
    8      AC007      5.0    SDME    0
    9      AC007      3.0    SDME    0
    10     AC007     31.4    SDME    1
    11     AC007      4.4    SDME    0
    12      CGT6      9.7    BTME    0
    13      CGT6     44.5    BTME    1
    14      TVF5      6.7    BTME    0
    15      TVF5      9.1    BTME    0
    16      TVF5     10.0    BTME    0
    17      BGD1      1.0    BTME    0
    18      BGD1      1.6     NON    0
    19       GHB     51.0     NON    1
    20       GHB     54.0     NON    1
    21       GHB      4.7     NON    0

这可行,但效率极低,并且希望有更好的方法来做到这一点。

标签: pythonpandasdictionarypandas-apply

解决方案


首先,您总共要遍历数据集四次,对于数据框中的每一行,您要遍历字典中的每个元素。你可以改变你的函数来遍历它一次。这将加快您的原始功能。尝试类似:

def myfilter(df, idCol, valCol, mydict):

    for index,row in df.iterrows():
        value = mydict.get(row[idCol])
        if row[valCol] >= value:
            df['chk'] = 1
        else:
            df['chk'] = 0

    return df

推荐阅读