Применить функцию к строкам фрейма данных

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

я пробовал purrr map_dbl а также rowwise но не могу заставить ни работать. Любые предложения, пожалуйста?

#sample df
df <- data.frame(Y=c("A","B","B","A","B"),
                  X=c(1,5,8,23,31))

#required result
Res <- data.frame(Y=c("A","B","B","A","B"),
                  X=c(1,5,8,23,31),
                  NewVal=c(10,500,800,230,3100)
                  )

#use mutate and map or rowwise etc
Res <- df %>%
  mutate(NewVal=map_dbl(.x=.,.f=FnAdd(.)))

Res <- df %>%
  rowwise() %>% 
  mutate(NewVal=FnAdd(.))


#sample fn
FnAdd <- function(Data){

  if(Data$Y=="A"){
    X=Data$X*10
  }  

  if(Data$Y=="B"){
    X=Data$X*100
  } 
  return(X)
}

2 ответа

Решение

Если есть несколько значений, лучше иметь key/val набор данных, присоединиться, а затем выполнить умножение

keyVal <- data.frame(Y = c("A", "B"), NewVal = c(10, 100))
df %>%
   left_join(keyVal) %>%
   mutate(NewVal = X*NewVal)
#  Y  X NewVal
#1 A  1     10
#2 B  5    500
#3 B  8    800
#4 A 23    230
#5 B 31   3100

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

FnAdd <- function(Data){
   Data %>%
      mutate(NewVal = case_when(Y == "A" ~ X * 10,
                                Y == "B" ~ X *100,
                                TRUE ~ X)) 
}

FnAdd(df)
#   Y  X NewVal
#1 A  1     10
#2 B  5    500
#3 B  8    800
#4 A 23    230
#5 B 31   3100

Вы изначально искали решение с использованием dplyr's rowwise(), так что вот это решение. Преимущество этого подхода в том, что вам не нужно создавать отдельную функцию.

Вот версия с использованием if()

   df %>% 
   rowwise() %>% 
   mutate(NewVal = ifelse(Y == "A", X * 10,
                          ifelse(Y == "B", X * 100)))

и вот версия, использующая case_when:

df %>% 
   rowwise() %>% 
   mutate(NewVal = case_when(Y == "A" ~ X * 10,
                             Y == "B" ~ X * 100))
Другие вопросы по тегам