Расстояние до ближайшего соседа для k = 1 в единицах времени

map может быть намного быстрее, чем replace

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

Исчерпывающее сопоставление

В этом случае форма очень проста:

df['col1'].map(di)       # note: if the dictionary does not exhaustively map all
                         # entries then non-matched entries are changed to NaNs

Хотя map чаще всего принимает функцию как свой аргумент, она может альтернативно принимать словарь или серию: Документация для Pandas.series.map

Неисчерпывающее сопоставление

Если у вас есть не исчерпывающее отображение и вы хотите сохранить существующие переменные для несоответствий, вы можете добавить fillna:

df['col1'].map(di).fillna(df['col1'])

, как в ответе @ jpp здесь: Заменить значения в серии pandas с помощью словаря эффективно

Тесты

Используя следующие данные с версией pandas 0.23.1:

di = {1: "A", 2: "B", 3: "C", 4: "D", 5: "E", 6: "F", 7: "G", 8: "H" }
df = pd.DataFrame({ 'col1': np.random.choice( range(1,9), 100000 ) })

и тестируя с %timeit, похоже, что map примерно в 10 раз быстрее, чем replace.

Обратите внимание, что ваше ускорение с map будет отличаться в зависимости от ваших данных. Самое большое ускорение, похоже, связано с большими словарями и исчерпывающими заменами. См. Ответ @jpp (см. Выше) для более подробных тестов и обсуждения.

2
задан iprof0214 16 January 2019 в 22:02
поделиться

2 ответа

Вы можете преобразовать даты в эпоху, используя этот код:

import time
date_time = '2016-05-03 00:00:00'
pattern = '%Y-%m-`enter code here`%d %H:%M:%S'
epoch = int(time.mktime(time.strptime(date_time, pattern)))

Затем просто вычтите значение из соседнего значения. Обратите внимание, что результат будет в миллисекундах, поэтому вам придется поделить на (1000 * 60 * 60 * 24), чтобы преобразовать его в дни.

0
ответ дан Jim Mirzakhalov 16 January 2019 в 22:02
поделиться

Привет, здесь возможное решение с использованием только панд.

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

sorted_df = sorted_df = df.sort_values('Date')
result_df = sorted_df.groupby('A_key').apply(nearest_date_distance)

Так что теперь давайте посмотрим, что у нас есть внутри функции nearest_date_distance Функция основана на том факте, что Дата будет отсортирована, поэтому мы вычисляем время до даты и время до даты после, разницу между текущим днем ​​и следующим день отрицателен, поэтому мы добавляем .abs(). Наконец, мы берем минимум между этими двумя расстояниями (кстати, оператор min не примет пропущенное значение (NaT), которое у вас есть для первой строки time_to_before и последней строки времени после)

def nearest_date_distance(sub):
    time_to_before = sub['Date'].diff()
    time_to_after = sub['Date'].diff(-1).abs()
    nearest_date_distance = pd.concat([time_to_before, time_to_after],axis=1).min(axis=1)
    nearest_date_distance.name = 'Distance'
    return nearest_date_distance

Наконец, я немного соврал result_df, это будет MultiIndex Serie (не датафрейм) этой формы:

A_key  id
A1     0    145 days
       1    145 days
A2     2      0 days
       3      0 days
A3     4    163 days
       5     26 days
       6     26 days
A4     7      0 days
       8      0 days

Мы можем легко преобразовать его в DataFrame, и правильное именование нашего исходного индекса помогает увидеть, что все проиндексировано так же, как в оригинальном df.

result_df =sorted_df.groupby('A_key').apply(nearest_date_distance).reset_index(level=0)

    A_key   Distance
id      
0   A1  145 days
1   A1  145 days
2   A2  0 days
3   A2  0 days
4   A3  163 days
5   A3  26 days
6   A3  26 days
7   A4  0 days
8   A4  0 days

, и если вам нужна дата в итоговом кадре данных result_df['Date'] = df['Date'], то добейтесь цели:)

0
ответ дан abcdaire 16 January 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: