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 (см. Выше) для более подробных тестов и обсуждения.
Вы можете преобразовать даты в эпоху, используя этот код:
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), чтобы преобразовать его в дни.
Привет, здесь возможное решение с использованием только панд.
Давайте дадим имя текущему индексу (для удобства и будем уверены, что мы все хорошо восстановим). Для сортировки по дате и применения функции к каждой группе важно отметить, что мы будем полагаться на тот факт, что панды сохраняют порядок строк внутри группы (см. документацию)
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']
, то добейтесь цели:)