Более быстрый метод для умножения значений поиска столбцов с векторизацией - PullRequest
0 голосов
/ 25 января 2019

У меня есть два Dataframes, один содержит значения и является рабочим набором данных (postsolutionDF), а другой просто для справки в качестве справочной таблицы (factorimportpcntDF). Цель состоит в том, чтобы добавить в postsolutionDF столбец, содержащий произведение значений поиска из каждой строки postsolutionDF (имя нового столбца = num_predict). Затем этот продукт умножается на 2700. Например, в первом ряду рабочие значения равны 0,5, 2, -6. Эквивалентные значения поиска для них составляют 0.1182, 0.2098 и 0.8455. Произведение этих значений составляет 0,0209, что при умножении на 2700 составляет 56,61, как показано в выходных данных.

Приведенный ниже код работает для этого упрощенного примера, но в реальном решении он очень медленный (строки 1,6 мм x 15 пронумерованных столбцов). Я уверен, что есть лучший способ сделать это, удалив цикл 'for k in range', но я борюсь с тем, как с тех пор уже применяется apply к строкам. Я нашел много косвенных решений, но пока что ничего не помогло в моей ситуации. Спасибо за любую помощь.

import pandas as pd
import numpy as np

postsolutionDF = pd.DataFrame({'SCRN' : (['2019-01-22-0000001', '2019-01-22-0000002', '2019-01-22-0000003']), '1' : 0.5,
                               '2' : 2, '3' : ([-6, 1.0, 8.0])})
postsolutionDF = postsolutionDF[['SCRN', '1', '2', '3']]
print('printing initial postsolutionDF..')
print(postsolutionDF)

factorimportpcntDF = pd.DataFrame({'F1_Val' : [0.5, 1, 1.5, 2], 'F1_Pcnt' : [0.1182, 0.2938, 0.4371, 0.5433], 'F2_Val'
: [2, 3, np.nan, np.nan], 'F2_Pcnt' : [0.2098, 0.7585, np.nan, np.nan], 'F3_Val' : [-6, 1, 8, np.nan], 'F3_Pcnt' :
    [0.8455, 0.1753, 0.072, np.nan]})

print('printing factorimportpcntDF..')
print(factorimportpcntDF)

def zero_filter(row): # row is series
    inner_value = 1
    for k in range(1, 4): # number of columns in postsolutionDF with numeric headers, dynamic in actual code
        inner_value *= factorimportpcntDF.loc[factorimportpcntDF['F'+str(k)+'_Val']==row[0+k], 'F'+str(k)+'_Pcnt'].values[0]
    inner_value *= 2700
    return inner_value

postsolutionDF['num_predict'] = postsolutionDF.apply(zero_filter, axis=1)
print('printing new postsolutionDF..')
print(postsolutionDF)

Вывод на печать:

C:\ProgramData\Anaconda3\python.exe C:/Users/Eric/.PyCharmCE2017.3/config/scratches/scratch_5.py
printing initial postsolutionDF..
                 SCRN    1  2    3
0  2019-01-22-0000001  0.5  2 -6.0
1  2019-01-22-0000002  0.5  2  1.0
2  2019-01-22-0000003  0.5  2  8.0
printing factorimportpcntDF..
   F1_Pcnt  F1_Val  F2_Pcnt  F2_Val  F3_Pcnt  F3_Val
0   0.1182     0.5   0.2098     2.0   0.8455    -6.0
1   0.2938     1.0   0.7585     3.0   0.1753     1.0
2   0.4371     1.5      NaN     NaN   0.0720     8.0
3   0.5433     2.0      NaN     NaN      NaN     NaN
printing new postsolutionDF..
                 SCRN    1  2    3  num_predict
0  2019-01-22-0000001  0.5  2 -6.0    56.610936
1  2019-01-22-0000002  0.5  2  1.0    11.737312
2  2019-01-22-0000003  0.5  2  8.0     4.820801

Process finished with exit code 0

1 Ответ

0 голосов
/ 18 апреля 2019

Я не уверен, как это сделать в нативных пандах, но если вы вернетесь к NumPy, это довольно легко.

Функция numpy.interp предназначена для интерполяции между значениями в таблице поиска, но если входные значения точно соответствуют значениям в таблице поиска (как у вас), это становится просто простым поиском вместо интерполяции.

postsolutionDF['1new'] = np.interp(postsolutionDF['1'].values, factorimportpcntDF['F1_Val'], factorimportpcntDF['F1_Pcnt'])
postsolutionDF['2new'] = np.interp(postsolutionDF['2'].values, factorimportpcntDF['F2_Val'], factorimportpcntDF['F2_Pcnt'])
postsolutionDF['3new'] = np.interp(postsolutionDF['3'].values, factorimportpcntDF['F3_Val'], factorimportpcntDF['F3_Pcnt'])
postsolutionDF['num_predict'] = postsolutionDF['1new'] * postsolutionDF['2new'] * postsolutionDF['3new'] * 2700
postsolutionDF.drop(columns=['1new', '2new', '3new'], inplace=True)

Дает вывод:

In [167]: postsolutionDF
Out[167]: 
                 SCRN    1  2    3  num_predict
0  2019-01-22-0000001  0.5  2 -6.0    56.610936
1  2019-01-22-0000002  0.5  2  1.0    11.737312
2  2019-01-22-0000003  0.5  2  8.0     4.820801

Я должен был добавить factorimportpcntDF, чтобы все столбцы имели 4 значения, иначе поиск наибольшего значения для столбца не сработал бы. Вы можете просто использовать одно и то же значение несколько раз или разбить его на 3 таблицы поиска, если хотите, тогда столбцы могут иметь разную длину.

factorimportpcntDF = pd.DataFrame({'F1_Val' : [0.5, 1, 1.5, 2], 'F1_Pcnt' : [0.1182, 0.2938, 0.4371, 0.5433],
'F2_Val' : [2, 3, 3, 3], 'F2_Pcnt' : [0.2098, 0.7585, 0.7585, 0.7585],
'F3_Val' : [-6, 1, 8, 8], 'F3_Pcnt' : [0.8455, 0.1753, 0.072, 0.072]})

Обратите внимание, что в документации указано, что ваши столбцы F1_val и т. Д. Должны располагаться в возрастающем порядке (ваши здесь, только к вашему сведению). В противном случае interp будет работать, но не обязательно даст хорошие результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...