Одновременный обход векторов в R

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

На другом языке я бы сделал одновременный обход двух отсортированных векторов времени. т.е. линейный поиск от начала старого вектора времени до тех пор, пока я не найду время, ближайшее к первому элементу в новом векторе времени, а затем продолжаю с этой точки в старом векторе, чтобы найти время, ближайшее ко второму элементу в новом векторе. и т. д. Это дает решение, равное O(n).

Ключевым моментом здесь является то, что два вектора времени имеют разную длину, а элементы не связаны друг с другом, поэтому что-то вроде map2 или walk2 — это не то, что мне нужно.

Я могу реализовать одновременную прогулку с помощью цикла for (см. код ниже), и это работает, но медленно. У меня также есть другое решение, которое больше похоже на R codey, но оно O(n^2), так что оно также оказывается медленным. Есть ли способ R сделать это, используя внутренние реализации R, чтобы получить решение O (n)?

В качестве альтернативы, есть ли функция R, которая могла бы заменить мой get_closest() бинарным поиском, чтобы, по крайней мере, это было O (nlogn)?

Из моих поисков я подозреваю, что ответ будет таким: «напишите функцию C, которую вы вызываете из R», но я довольно новичок в R, поэтому я хотел проверить, что я ничего не упустил.

Обновлено:

Я должен был четко указать, что значения в new_times могут не существовать в old_times. Я хочу найти индекс в old_times, где время ближе всего к каждой записи в new_times. В моем реальном приложении я буду делать линейную интерполяцию, но этот вопрос касается только поиска ближайшего соседа.

library(tidyverse)

# input values given
old_times  <- c(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
old_values <- c(3, 7, 6, 7,  8,  9,  7,  6,  4,  6)
new_times  <- c(4.1, 9.6, 12.3, 17.8)

Желаемый результат

new_values <- c(7, 8, 9, 4)

Моя попытка

new_values <- rep(NA, length(new_times))
old_index  <- 1

for (new_index in 1:length(new_times)) {
  while (old_index < length(old_times) &&
         old_times[old_index] < new_times[new_index]) {
    old_index <- old_index + 1
  }

  # I could now do interpolation if the value of new_times is in between
  # two values in old_times.  The key is I have a correspondence that
  # new_times[new_index] is close in time to old_times[old_index].
  new_values[new_index] <- old_values[old_index]
}


# Here's an alternative way to do it that uses more R internals,
# but winds up being O(n^2).

# Get the index in old_times closest to new_time.
# This is O(n).
get_closest <- function(new_time, old_times) {
  return(which.min(abs(new_time - old_times)))
}

# Call get_closest on each element of new_times.
# This is O(n^2).
new_indices <- unlist(map(new_times, get_closest, old_times))

# Slice the list of old values to get new values.
new_values2 <- old_values[new_indices]
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
97
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Мы можем использовать match

old_values[match(new_times, old_times)]
# [1] 7 8 9 4

match(new_times, old_times) возвращает «вектор позиций (первых) совпадений его первого аргумента во втором»., т.е.

# [1] 2 5 6 9

Мы можем использовать этот результат для извлечения желаемых значений из old_values с помощью [.


Мы также можем использовать %in%, который возвращает логический вектор.

old_values[old_times %in% new_times]

Благодаря @Андрей

Хорошо, это выглядит многообещающе. Что, если значения в new_times не в old_times, а я просто хочу получить индекс ближайшей записи? Я упустил это из виду в своем примере, чтобы код не стал слишком длинным, но в моем реальном приложении он может запросить значение в момент времени 2,5, и мне придется интерполировать.

Bob Steinke 09.04.2019 22:20

В качестве «альтернативы» old_values[old_times %in% new_times] делает то же самое под капотом. То есть см. ?match. Я обнаружил, что %in% обычно лучше масштабирует маленький (во многих случаях незаметно).

Andrew 09.04.2019 22:22

@BobSteinke Лучше всего создать минимальный пример и показать ожидаемый результат. Возможно, вы захотите задать новый вопрос.

markus 09.04.2019 22:23
Ответ принят как подходящий

Похоже, что лучше всего для этого использовать data.table. Я узнал об этом в этом другом вопросе:

Найти ближайшее значение в векторе с помощью бинарного поиска

Возможна оптимизация для data.table, если он знает, что векторы поиска и поиска отсортированы, он может выполнять поиск O (n) вместо O (nlogn), но data.table уже очень быстро в мое приложение.

Другие вопросы по теме