Как векторизовать функцию подмножества в R?

Мне повезло с векторизацией некоторых функций, что отлично подходит для чистого кода, избегания циклов и скорости.

Однако мне не удалось векторизовать какую-либо функцию, которая подмножает фрейм данных на основе входных данных функции.

Пример

Например. Эта функция хорошо работает, когда она получает элементы

test_funct <- function(sep_wid, sep_len) {
    iris %>% filter(Sepal.Width > sep_wid & Sepal.Length < sep_len) %>% .$Petal.Width %>% sum
}

test_funct(4, 6)

# [1] 0.7 # This works nicely

Но при попытке предоставить векторы в качестве входных данных для этой функции:

sep_wid_vector <- c(4, 3.5, 3)
sep_len_vector <- c(6, 6, 6.5)


test_funct(sep_wid_vector, sep_len_vector)

[1] 9.1 

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

# 0.7    4.2     28.5 

Для удобства здесь вывод, как если бы все они запускались отдельно.

test_funct(4, 6) # 0.7
test_funct(3.5, 6) # 4.2
test_funct(3, 6.5) # 28.5

Как я могу векторизовать функцию, которая подмножает данные на основе своих входных данных, чтобы она могла получать векторные входные данные?

Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
6
0
265
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Проблема в том, что filter принимает векторные входные данные, поэтому он будет перерабатывать векторы в сравнениях Sepal.width и Sepal.length.

Один из способов сделать это — использовать map2 из пакета purrr:

map2_dbl(sep_wid_vector, sep_len_vector, test_funct)

Конечно, вы могли бы обернуть это в функцию. Вы также можете рассмотреть возможность передачи фрейма данных в качестве параметра функции.

@thothal отличная находка с purrr::map2_dbl. Для полноты картины также работает mapply(test_funct, sep_wid_vector, sep_len_vector)

stevec 09.04.2019 11:04

Вы можете использовать Vectorize:

tv <- Vectorize(test_funct)

tv(sep_wid_vector, sep_len_vector)
# [1]  0.7  4.2 28.5

Это в основном обертка вокруг mapply. Имейте в виду, что под капотом вы запускаете функцию *apply, которая также является своего рода циклом.

Вот один из способов использования sapply

# function using sapply
test_funct <- function(sep_wid, sep_len) {
  sapply(seq_along(sep_wid), function(x) {
    sum(iris$Petal.Width[iris$Sepal.Width > sep_wid[x] & iris$Sepal.Length < sep_len[x]])
  })
}

# testing with single value
test_funct(4,6)
[1] 0.7

# testing with vectors
test_funct(sep_wid_vector, sep_len_vector)
[1]  0.7  4.2 28.5

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