Посчитайте количество регистров в интервал и расположение


Недавно я спросил, как можно подсчитать количество регистров интервал как ответил https://stackoverflow.com/questions/49240140/count-number-of-registers-in-interval.

Решение работает отлично, но мне пришлось адаптировать ее также принять во внимание некоторые ключевые локализации.

Я сделал это с помощью следующего кода:

def time_features(df, time_key, T, location_key, output_key):
    """
    Create features based on time such as: how many BDs are open in the same GRA at this moment (hour)?
    """ 
    from datetime import date
    assert np.issubdtype(df[time_key], np.datetime64)
    output = pd.DataFrame()

    grouped = df.groupby(location_key)
    for name, group in grouped:
        # initialize times registers open as 1, close as -1
        start_times = group.copy()
        start_times[time_key] = group[time_key]-pd.Timedelta(hours=T)
        start_times[output_key] =  1

        aux = group.copy()
        all_times = start_times.copy()
        aux[output_key] = -1  
        all_times = all_times.append(aux, ignore_index=True)

        # sort by time and perform a cumulative sum to get opened registers
        # (subtract 1 since you don't want to include the current time as opened)
        all_times = all_times.sort_values(by=time_key)
        all_times[output_key] = all_times[output_key].cumsum() - 1

        # revert the index back to original order, and truncate closed times
        all_times = all_times.sort_index().iloc[:len(all_times)//2]
        output = output.append(all_times, ignore_index=True)
    return output

Выход:

time    loc1    loc2
0   2013-01-01 12:56:00 1   "a"
1   2013-01-01 12:00:12 1   "b"
2   2013-01-01 10:34:28 2   "c"
3   2013-01-01 09:34:54 2   "c"
4   2013-01-01 08:34:55 3   "d"
5   2013-01-01 08:34:55 5   "d"
6   2013-01-01 16:35:19 4   "e"
7   2013-01-01 16:35:30 4   "e"

time_features(df, time_key='time', T=2, location_key='loc1', output_key='count')

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



Комментарии
1 ответ

Рассмотреть не расширять таблицу данных внутри for петли, но построить список или словарь, а затем объединить все таблицы данных элементов вне петли.

Расширение объектов внутри цикла вызывает значительные ресурсы памяти для выделения до и после блоков с большим количеством копирование объектов , чтобы сделать так. Работает один звонок на улице должны существенно работать быстрее, так как практически никакое копирование не сделано.

Конкретно изменения:

output = pd.DataFrame()

К списку:

output = []

А затем добавить в список внутри цикла, а затем pd.concat(list) за пределами петли.

def time_features(df, time_key, T, location_key, output_key):
"""
Create features based on time such as: how many BDs are open in the same GRA at this moment (hour)?
"""
from datetime import date
assert np.issubdtype(df[time_key], np.datetime64)
output = []

grouped = df.groupby(location_key)
for name, group in grouped:
# initialize times registers open as 1, close as -1
start_times = group.copy()
start_times[time_key] = group[time_key]-pd.Timedelta(hours=T)
start_times[output_key] = 1

aux = group.copy()
all_times = start_times.copy()
aux[output_key] = -1
all_times = all_times.append(aux, ignore_index=True)

# sort by time and perform a cumulative sum to get opened registers
# (subtract 1 since you don't want to include the current time as opened)
all_times = all_times.sort_values(by=time_key)
all_times[output_key] = all_times[output_key].cumsum() - 1

# revert the index back to original order, and truncate closed times
all_times = all_times.sort_index().iloc[:len(all_times)//2]
# APPEND TO LIST
output.append(all_times)

# CONCATENATE ALL DF ELEMENTS
final_df = pd.concat(output, ignore_index=True)

return final_df

0
ответ дан 23 апреля 2018 в 06:04 Источник Поделиться