Создание нового столбца из двух столбцов с использованием словаря в Pandas - PullRequest
0 голосов
/ 29 января 2019

Я хочу создать столбец на основе группы и порога для отсечения из другого столбца для каждой группы сгруппированного столбца.

Ниже приведен кадр данных:

     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

Итак, яЯ создал словарь на основе каждой группы столбца «identifier» следующим образом:

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

Поэтому моя цель - создать новый столбец, скажем «chk», на основе следующего условия:

Если столбец «identifier» соответствует ключу в словаре «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

Это работает, но крайне неэффективно и хотелось бы гораздо лучший способ сделать это.

Ответы [ 2 ]

0 голосов
/ 29 января 2019

Это должно быть быстрее:

def func(identif, value):
    if identif in md:
        if value >= md[identif]:
            return 1.0
        else:
            return 0.0
    else:
        return np.NaN

df['chk'] = df.apply(lambda row: func(row['identif'], row['myvalue']), axis=1)

Время на этом небольшом примере:

CPU times: user 1.64 ms, sys: 73 µs, total: 1.71 ms
Wall time: 1.66 ms

Время вашей версии:

CPU times: user 8.6 ms, sys: 1.92 ms, total: 10.5 ms
Wall time: 8.79 ms

Хотя на такоммаленький пример, это не убедительно.

0 голосов
/ 29 января 2019

Во-первых, вы обходите свой набор данных всего четыре раза, для каждой строки во фрейме данных вы просматриваете каждый элемент в своем словаре.Вы можете изменить свою функцию, чтобы пройти ее один раз.Это ускорит вашу первоначальную функцию.Попробуйте что-то вроде:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...