Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use mutate on list?

Tags:

r

dplyr

What is the correct way to mutate a list? In this specific case the list is being returned by split

library(dplyr)
csv<-data.frame(participant_number=c(1,1,1,2,2),SelfEsteem=c(3,4,2,1,3))
csv<-csv%>%split(.,.$participant_number)%>%mutate(.,var(.$SelfEsteem))

Error:

Error in UseMethod("mutate_") : 
  no applicable method for 'mutate_' applied to an object of class "list"

UPDATE In answer to comments: I intend to calculate the variance of SelfEsteem each group (the grouping var is participant_number). If I try group_by I do not get the expected result....Why?

library(dplyr)

#Please note I changed the dataframe to make my point about variance differences more obvious
csv<-data.frame(participant_number=c(1,1,1,2,2),SelfEsteem=c(3,4,2,1,3))

csv<-csv%>%group_by(participant_number)%>%mutate(.,SE_variance=var(.$SelfEsteem))

#var(c(3,4,2)) #1
#var(c(1,3))  #2

Expected:

        participant_number SelfEsteem SE_variance
(dbl)            (dbl)       (dbl)
1                  1          3         1
2                  1          4         1
3                  1          2         1
4                  2          1         2
5                  2          3         2
like image 808
Rilcon42 Avatar asked Feb 07 '23 17:02

Rilcon42


2 Answers

Your attempt with group_by fails because you override mutate's search path. Mutate uses non-standard evaluation, so it will look for variables first among the columns of it's data argument.

When you use pipes (%>%), a dot . refers to the whole data frame, and .$SelfEsteem refers to the whole SelfEsteem column from the whole data frame.

You just need to simplify a little bit (not override the defaults) to get the expected result.

csv %>% 
  group_by(participant_number) %>%
  mutate(SE_variance = var(SelfEsteem))
# Source: local data frame [5 x 3]
# Groups: participant_number [2]
# 
#   participant_number SelfEsteem SE_variance
#                (dbl)      (dbl)       (dbl)
# 1                  1          3           1
# 2                  1          4           1
# 3                  1          2           1
# 4                  2          1           2
# 5                  2          3           2
like image 67
Gregor Thomas Avatar answered Feb 09 '23 07:02

Gregor Thomas


If you really need to use a list object, you can mutate a list using map from the purrr library:

library(dplyr) 
library(purrr) 

csv %>% 
    split(.,.$participant_number) # your list 
    map(~mutate(.,var(.$SelfEsteem))) # this will mutate a list 

Now, you can put everything back together with bind_rows()

csv %>% 
  split(.,.$participant_number) %>% 
  map(~mutate(.,var(.$SelfEsteem))) %>% 
  bind_rows()

and you get what you need.

like image 29
giac Avatar answered Feb 09 '23 07:02

giac