Applying mutate_at conditionally to specific rows in a dataframe in R

别等时光非礼了梦想. 提交于 2020-06-23 04:11:09

问题


I have a dataframe in R that looks like the following:

a  b  c  condition
1  4  2  acap
2  3  1  acap
2  4  3  acap
5  6  8  ncap
5  7  6  ncap
8  7  6  ncap

I am trying to recode the values in columns a, b, and c for condition ncap (and also 2 other conditions not pictured here) while leaving the values for acap alone.

The following code works when applied to the first 3 columns. I am trying to figure out how I can apply this only to rows that I specify by condition while keeping everything in the same dataframe.

df = df %>%
     mutate_at(vars(a:c), function(x) 
     case_when x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)

This is the expected output.

a  b  c  condition
1  4  2  acap
2  3  1  acap
2  4  3  acap
1  2  4  ncap
1  3  2  ncap
4  3  2  ncap

I've looked around for an answer to this question and am unable to find it. If someone knows of an answer that already exists, I would appreciate being directed to it.


回答1:


We can use the case_when on a condition created with row_number i.e. if the row number is 4 to 6, subtract 4 from the value or else return the value

df %>% 
   mutate_at(vars(a:c), funs(case_when(row_number() %in% 4:6 ~ . - 4L, 
                                       TRUE ~ .)))
#  a b c condition
#1 1 4 2      acap
#2 2 3 1      acap
#3 2 4 3      acap
#4 1 2 4      ncap
#5 1 3 2      ncap
#6 4 3 2      ncap

If this is based on the value instead of the rows, create the condition on the value

df %>% 
   mutate_at(vars(a:c), funs(case_when(. %in% 5:8 ~ . - 4L, 
                                       TRUE ~ .)))
#  a b c condition
#1 1 4 2      acap
#2 2 3 1      acap
#3 2 4 3      acap
#4 1 2 4      ncap
#5 1 3 2      ncap
#6 4 3 2      ncap

Or if it is based on the value in the 'condition'

df %>% 
   mutate_at(vars(a:c), funs(case_when(condition == 'ncap' ~ . - 4L, 
                                       TRUE ~ .)))

Or without using any case_when

df %>% 
  mutate_at(vars(a:c), funs( . - c(0, 4)[(condition == 'ncap')+1]))
#  a b c condition
#1 1 4 2      acap
#2 2 3 1      acap
#3 2 4 3      acap
#4 1 2 4      ncap
#5 1 3 2      ncap
#6 4 3 2      ncap

In base R, we can do this by creating the index

i1 <- df$condition =='ncap'
df[i1, 1:3] <- df[i1, 1:3] - 4

data

df <- structure(list(a = c(1L, 2L, 2L, 5L, 5L, 8L), b = c(4L, 3L, 4L, 
 6L, 7L, 7L), c = c(2L, 1L, 3L, 8L, 6L, 6L), condition = c("acap", 
 "acap", "acap", "ncap", "ncap", "ncap")), class = "data.frame", 
 row.names = c(NA, -6L))



回答2:


You can use filter to apply recoding values to only specific rows (not equal to "acap" here)

library(dplyr)
df %>%
  filter(condition != "acap") %>%
  mutate_at(vars(a:c), function(x) 
  case_when(x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)) 

#  a b c condition
#1 1 2 4      ncap
#2 1 3 2      ncap
#3 4 3 2      ncap

If you need the entire dataframe back again we can do

df %>%
  filter(condition == "acap") %>%
  bind_rows(df %>%
     filter(condition != "acap") %>%
     mutate_at(vars(a:c), function(x) 
    case_when(x == 5 ~ 1, x == 6 ~ 2, x == 7 ~ 3, x == 8 ~ 4)))

#  a b c condition
#1 1 4 2      acap
#2 2 3 1      acap
#3 2 4 3      acap
#4 1 2 4      ncap
#5 1 3 2      ncap
#6 4 3 2      ncap


来源:https://stackoverflow.com/questions/51940709/applying-mutate-at-conditionally-to-specific-rows-in-a-dataframe-in-r

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!