Я пытаюсь получить точки данных, ближайшие к отметке времени запроса для нескольких независимых категорий, подобных этой (более подробный пример в сущности):

dt = pd.to_datetime(dt)
df_output = list()
for category in df.category.unique():
    df_temp = df[df.category == category]
    i = df_temp.index.get_loc(dt, method='nearest')
    latest = df_temp.iloc[i]
    df_output.append(latest)

pd.DataFrame(df_output)

Проблема с этим подходом в том, что он очень медленный (и, очевидно, кажется очень тупым). Профилирование предполагает, что узким местом является iloc, что кажется странным.

Как это сделать быстрее / правильнее? Есть ли способ получить результат сразу по всем категориям? (Я думаю о магии groupby)

Способен ли pandas на это, или мне следует переключиться на другой метод хранения таймсерий?

0
tales 2 Янв 2018 в 03:13

2 ответа

Лучший ответ

Pandas был создан для данных временных рядов, так что это хлеб с маслом. Попробуйте это для производительности:

dt = '2017-12-23 01:49:13'
df["timedelta"] = abs(df.index - pd.Timestamp(dt))
df.loc[df.groupby(by="category")["timedelta"].idxmin()].drop("timedelta", axis=1)

Это создает новый столбец с именем timedelta, названный в честь класса pandas.Timedelta, а затем с помощью groupby объединяет все категории, находит наименьшее значение timedelta в каждой и возвращает их индекс в .loc. Наконец я уронил колонку.

1
Tony 2 Янв 2018 в 00:51

Вы можете сделать это с помощью groupby, но вам все равно нужно будет использовать iloc. Вот решение:

dt = pd.to_datetime('2017-12-23 01:50:30')

def find(df):
    return pd.DataFrame(df.iloc[df.index.get_loc(dt, method='nearest')]).T

new_df = df.groupby('category').apply(find)
new_df


                                        category    value
category            
A           2017-12-23 01:50:21.687     A           1
B           2017-12-23 01:50:21.661     B           3

Если вам не нужен мультииндекс, указывающий категорию, вы можете просто удалить его следующим образом:

new_df.index = new_df.index.droplevel()
new_df

                            category    value

2017-12-23 01:50:21.687     A           1
2017-12-23 01:50:21.661     B           3
1
Oriol Mirosa 2 Янв 2018 в 00:55