Python - самый быстрый способ заполнить фрейм данных условием на основе индекса в другом фрейме данных - PullRequest
2 голосов
/ 10 марта 2019

У меня есть данные во входном фрейме данных (input_df).На основе индекса в другом контрольном фрейме данных (bm_df) я хотел бы создать третий фрейм данных (output_df), который заполняется на основе условия с использованием индексов в исходных двух фреймах данных.

Для каждой даты в индексе для bm_df я хотел бы заполнить свои выходные данные, используя самые последние данные, доступные в файле input_df, при условии, что данные имеют индексную дату до или равную дате в bm_df.,Например, в тематическом исследовании данные ниже выходного кадра данных для первой индексной даты (2019-01-21) будут заполнены данными из точки ввода input_df для 2019-01-21.Однако, если точка данных для 2019-01-21 не существует, она будет использовать 2019-01-18.

В данном случае используется сопоставление и обратная засыпка больших наборов данных для последних данных, доступных на указанную дату.,Я написал некоторый Python, чтобы сделать это для меня (который работает), однако я думаю, что, вероятно, есть более питонический и, следовательно, более быстрый способ реализации решения.Мой базовый набор данных, к которому он применяется, имеет большие измерения с точки зрения количества столбцов и длины столбцов, и поэтому я хотел бы получить что-то настолько эффективное, насколько это возможно - мое текущее решение работает слишком медленно при работе с полным набором данных, который я использую.

Любая помощь очень важна!

input_df:

index   data
2019-01-21  0.008
2019-01-18  0.016
2019-01-17  0.006
2019-01-16  0.01
2019-01-15  0.013
2019-01-14  0.017
2019-01-11  0.017
2019-01-10  0.024
2019-01-09  0.032
2019-01-08  0.012

bm_df:

index   
2019-01-21  
2019-01-14  
2019-01-07  

output_df:

index   data
2019-01-21  0.008
2019-01-14  0.017
2019-01-07  NaN

Пожалуйста, посмотрите код, который я сейчас использую:

import pandas as pd
import numpy as np

# Import datasets
test_index = ['2019-01-21','2019-01-18','2019-01-17','2019-01-16','2019-01-15','2019-01-14','2019-01-11','2019-01-10','2019-01-09','2019-01-08']    
test_data = [0.008, 0.016,0.006,0.01,0.013,0.017,0.017,0.024,0.032,0.012]
input_df= pd.DataFrame(test_data,columns=['data'], index=test_index)

test_index_2= ['2019-01-21','2019-01-14','2019-01-07']  
bm_df= pd.DataFrame(index=test_index_2)

#Preallocate
data_mat= np.zeros([len(bm_df)])

#Loop over bm_df index and find the most recent variable from input_df which from a date before the index date 
for i in range(len(bm_df)):
    #First check to see if there are no dates before the selected date, if true fill with NaN
    if sum(input_df.index <= bm_df.index[i])>0:
        data_mat[i] = input_df['data'][max(input_df.index[input_df.index <= bm_df.index[i]])]
    else:
        data_mat[i] = float('NaN')

output_df= pd.DataFrame(data_mat,columns=['data'],index=bm_df.index)

1 Ответ

1 голос
/ 10 марта 2019

Я не проверял время выполнения, но я бы полагался на join, который упоминается как эффективный в пандах документация :

... Эффективное объединение нескольких объектов DataFrame по индексу одновременно ...

И я бы использовал shift, чтобы получить значение для самой высокой даты перед искомой.

Все, что дают:

output_df = bm_df.join(input_df.shift(-1), how='left')

             data
2019-01-21  0.016
2019-01-14  0.017
2019-01-07    NaN

Этот подход действительно гораздо менее универсален, чем явные циклы. Это цена за векторизацию панд. Например, для условия меньше или равно код будет немного другим. Вот пример с дополнительной датой в bm_df, отсутствующей в input_df:

...
test_index_2= ['2019-01-21','2019-01-14','2019-01-13','2019-01-07']  
...
tmp_df = input_df.join(bm_df).fillna(method='bfill')
output_df = bm_df.join(tmp_df, how='inner')

И получаем, как и ожидалось:

             data
2019-01-21  0.008
2019-01-14  0.017
2019-01-13  0.017
2019-01-07  0.012
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...