#r
#r
Вопрос:
Я хочу создать новую переменную во фрейме данных, который использует справочную таблицу. Итак, у меня был df1 (dataframe), который имеет количество и срок. И мне нужно создать новую переменную «Premium», которая создает свои значения с помощью справочной таблицы.
Я пробовал функцию ifelse, но это слишком утомительно. Ниже приведена иллюстрация / пример
df1 <- data.frame(Amount, Term)
df1
# Amount Term
# 1 2500 23
# 2 3600 30
# 3 7000 45
# 4 12000 50
# 5 16000 38
И мне нужно создать новую переменную ‘Premium’, используя приведенную ниже таблицу поиска Premium.
Term
Amount 0-24 Mos 25-36 Mos 37-48 Mos 49-60 Mos
0 - 5,000 133 163 175 186
5,001 - 10,000 191 213 229 249
10,001 - 15,000 229 252 275 306
15,001 - 20,000 600 615 625 719
20,001 - 25,000 635 645 675 786
Таким образом, вывод для premium должен быть.
df1
# Amount Term Premium
# 1 2500 23 133
# 2 3600 30 163
# 3 7000 45 229
# 4 12000 50 306
# 5 16000 38 625
Комментарии:
1. Можете ли вы предоставить общий доступ к таблице поиска и df1 с помощью dput?
Ответ №1:
Данные
df1 <- structure(list(Amount = c(2500L, 3600L, 7000L, 12000L, 16000L),
Term = c(23L, 30L, 45L, 50L, 38L)),
class = "data.frame",
row.names = c(NA, -5L))
lkp <- structure(c(133L, 191L, 229L, 600L, 635L,
163L, 213L, 252L, 615L, 645L,
175L, 229L, 275L, 625L, 675L,
186L, 249L, 306L, 719L, 786L),
.Dim = 5:4,
.Dimnames = list(Amount = c("0 - 5,000", "5,001 - 10,000",
"10,001 - 15,000", "15,001 - 20,000",
"20,001 - 25,000"),
Term = c("0-24 Mos", "25-36 Mos", "37-48 Mos",
"49-60 Mos")))
Код
-
Сначала создайте верхние пределы для месяца и суммы, используя регулярные выражения из имен столбцов и строк (вы не размещали свои данные воспроизводимым способом, поэтому это регулярное выражение может нуждаться в адаптации на основе вашей реальной структуры справочной таблицы):
(month <- c(0, as.numeric(sub("\d -(\d ) Mos$", "\1", colnames(lkp))))) # [1] 0 24 36 48 60 (amt <- c(0, as.numeric(sub("^\d ,*\d* - (\d ),(\d )$", "\1\2", rownames(lkp))))) # [1] 0 5000 10000 15000 20000 25000
-
Получить позиции для каждого элемента
df1
с помощьюfindInterval
:(rows <- findInterval(df1$Amount, amt)) # [1] 1 1 2 3 4 (cols <- findInterval(df1$Term, month)) # [1] 1 2 3 4 3
-
Используйте эти индексы для подмножества матрицы поиска:
df1$Premium <- lkp[cbind(rows, cols)] df1 # Amount Term Premium # 1 2500 23 133 # 2 3600 30 163 # 3 7000 45 229 # 4 12000 50 306 # 5 16000 38 625
Ответ №2:
Чтобы получить то, что вы хотите, вам нужно упорядочить таблицу и классифицировать данные. Я предоставил потенциальный рабочий процесс для обработки таких ситуаций. Надеюсь, это полезно:
library(tidyverse)
df1 <- data.frame(
Amount = c(2500L, 3600L, 7000L, 12000L, 16000L),
Term = c(23L, 30L, 45L, 50L, 38L)
)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# functions for analysis ####
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
amount_tier_function <- function(x){
case_when(x <= 5000 ~ "Tier_5000",
x <= 10000 ~ "Tier_10000",
x <= 15000 ~ "Tier_15000",
x <= 20000 ~ "Tier_20000",
TRUE ~ "Tier_25000")
}
month_tier_function <- function(x){
case_when(x <= 24 ~ "Tier_24",
x <= 36 ~ "Tier_36",
x <= 48 ~ "Tier_48",
TRUE ~ "Tier_60")
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Recut lookup table headings ####
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
lookup_df <- data.frame(stringsAsFactors=FALSE,
amount_tier = c("Tier_5000", "Tier_10000", "Tier_15000", "Tier_20000",
"Tier_25000"),
Tier_24 = c(133L, 191L, 229L, 600L, 635L),
Tier_36 = c(163L, 213L, 252L, 615L, 645L),
Tier_48 = c(175L, 229L, 275L, 625L, 675L),
Tier_60 = c(186L, 249L, 306L, 719L, 786L)
)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# Join everything together ####
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
lookup_df_tidy <- lookup_df %>%
gather(mth_tier, Premium, - amount_tier)
df1 %>%
mutate(amount_tier = amount_tier_function(Amount),
mth_tier = month_tier_function(Term)) %>%
left_join(., lookup_df_tidy) %>%
select(-amount_tier, -mth_tier)
Комментарии:
1. Это решение потребует некоторого дополнительного кодирования в случае, если указаны новые месяцы или суммы. Возможно, вы могли бы автоматизировать кодирование уровня, чтобы избежать этого ручного шага.
2. Я согласен. Был бы признателен, если бы вы любезно предоставили несколько идей для автоматизации процесса многоуровневости.
3. Я бы использовал
regex
подход, аналогичный тому, который я использовал в своем ответе. В итоге у вас есть информация, уже закодированная в именах строк, и вы должны извлечь ее оттуда.