Как найти самое низкое значение во фрейме данных, соответствующее определенным критериям, и вернуть определенный столбец - PullRequest
2 голосов
/ 20 июня 2019

Во-первых, я довольно новичок в R, и я также начинаю задавать вопросы по SO, так что терпите меня, если я задаю глупые вопросы или не соблюдаю соглашения SO.

I 'Я пытаюсь найти лучший тип подписки для нескольких пользователей на основе их прежнего поведения при вызове.До сих пор мне удавалось ок.сопоставьте 98 000 строк, чтобы рассчитать эффективные затраты с (переменным) числом типов подписки.

effective costs

Также есть фрейм данных с прогнозируемыми затратами на тип подписки на каждый месяц: predicted costs

Сейчас я пытаюсь найти лучшую подпискуукажите, где стоимость ниже текущей для каждого пользователя и месяца.Я сделаю объединение, чтобы показать, какие результаты я ожидаю:

comparison

Таким образом, в месяц 2019-01 затраты на subscription_2 ниже, чем текущая подписка наUser1, поэтому subscription2 должна быть рекомендацией.Для месяцев 2019-02 и 2019-03 рекомендации отсутствуют, так как нет типов подписки с более низкими затратами.

Для User2 тип подписки subscription_3 должен быть рекомендацией во все месяцы, поскольку эти затратывсегда ниже текущей подписки.

В настоящее время я следую за курсами на DataCamp.com, и я почти уверен, что это почти ОЧЕНЬ базовое действие в r, но мне нужен кто-то, чтобы направить меня в правильном направлении.

Это то, что у меня пока есть:

library(dplyr)

effective.costs <- data.frame(
  user = c(rep("User1", 3), rep("User2", 3)),
  month = c(rep(c("2019-01", "2019-02", "2019-03"), 2)),
  current_subscription = c(rep("subscription_1", 3), rep("subscription_2", 3)),
  costs = c(70, 20, 50, 150, 130, 170)
)

predicted.costs <- data.frame(
  user = c(rep("User1", 9), rep("User2", 9)),
  month = c(rep("2019-01",3), rep("2019-02", 3), rep("2019-03", 3)),
  subscription = c(rep(c("subscription_1", "subscription_2", "subscription_3"), 6)),
  calculated_costs = c(
    c(70, 50, 110, 20, 50, 70, 50, 80, 120), 
    c(190, 150, 110, 210, 130, 110, 250, 170, 110)
    )
)

comparison <- merge(effective.costs, predicted.costs, by = c("user", "month"))

getRecommendation <- function(x) {
  subscription <- predicted.costs %>% 
    filter(
      calculated_costs < x['costs'] & 
      user == x['user'] & 
      month == x['month']
    ) %>%
    arrange(calculated_costs) %>%
    select(subscription) 
  subscription <- ifelse(
    length(subscription) > 0, 
    as.character(subscription[1, 1]), 
    NA
  )
  # I know return is not needed, but I'm used to it... :-)
  return(subscription)
}

effective.costs$recommendation <- apply(effective.costs, 1, getRecommendation)

View(effective.costs)

Самая важная часть здесь, вероятно, это функция getRecommendation:

getRecommendation <- function(x) {
  subscription <- predicted.costs %>% 
    filter(
      calculated_costs < x['costs'] & 
      user == x['user'] & 
      month == x['month']
    ) %>%
    arrange(calculated_costs) %>%
    select(subscription) 
  subscription <- ifelse(
    length(subscription) > 0, 
    as.character(subscription[1, 1]), 
    NA
  )
  # I know return is not needed, but I'm used to it... :-)
  return(subscription)
}

, которую я пытаюсьна apply на каждую строку в effective.costs:

effective.costs$recommendation <- apply(effective.costs, 1, getRecommendation)

Хотя это дает мне правильный вывод для User2, в настоящее время я считаю, что это совпадение, поскольку нет никаких рекомендаций для User1, дажеесли он будет на месяц 2019-01:

wrong result

Может кто-нибудь, пожалуйста, подтолкнуть меня в правильном направлении?

Спасибо!

1 Ответ

1 голос
/ 20 июня 2019

Это устраняет функции apply и getRecommendation.R векторизовано, поэтому мы должны стараться мыслить по столбцам как можно больше.

comparison <- merge(effective.costs, predicted.costs, by = c("user", "month"))

comparison%>%
  mutate(net_savings = calculated_costs-costs)%>%
  group_by(user, month)%>%
  filter(net_savings == min(net_savings))%>%
  slice(1) #for ties

Проблема с вашей функцией apply() заключается в том, что apply() приводит data.frame к матрице.Матрица может иметь только один тип класса - в этом случае вы сравниваете число со строкой в ​​calculated_costs < x['costs'].

В частности, оценка составляет calculated_costs < ' 50', где есть дополнительное место для двухзначных чисел.По какой-либо причине 50 < ' 70' оценивает FALSE, тогда как 110 < '190' оценивает TRUE.

Решение состоит в том, чтобы в этом случае по-другому подходить к проблеме.Нет необходимости выполнять операции по строке через apply.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...