ADP (R)

[R 연습 문제] tapply 코드를 purrr::map 으로 변환하기

멋쟁이천재사자 2022. 7. 20. 14:47

1. 문제

chickwts 데이터를 feed 별로 weight 의 합을 tapply 함수를 이용하여 다음과 같이 구할 수 있다.

> tapply(chickwts$weight,chickwts$feed,sum)
   casein horsebean   linseed  meatmeal   soybean sunflower 
     3883          1602       2625          3046        3450        3947

tapply 함수 대신 split 함수와 purrr 패키지의 map_* 함수를 이용하여 동일한 결과를 구하라

 

2. 정답

library(purrr)
chickwts %>% 
     split(.$feed)   %>% 
     map_df(~sum(.$weight))

3.시행 착오

purrr 을 이용해야 진정한 R 사용자 ! 라고 하여 연습하였습니다.

 

?map 을 통해 설명서를 보았습니다.

 


mtcars %>%
  split(.$cyl) %>%
  map(~ lm(mpg ~ wt, data = .x)) %>%
  map(summary) %>%
  map_dbl("r.squared")
  
한번 돌려보니 실행이 잘되서 이 코드를 조금 수정해보았습니다.
  
chickwts %>% 
     split(.$feed) %>%                    #여기까지는 쉬운데...
     map(~sum, data=weight)        #성공하고 다시보니 data = 는 lm 에 필요한 argument 였음


원하는 결과가 아닙니다.

chickwts %>% 
     split(.$feed) %>%
     map_dbl(~sum, data=weight)                                      #map 대신 결과가 숫자이니 map_dbl 이면 될까하여 시도
Error: Can't coerce element 1 from a builtin to a double  # builtin 을  double 로 강제로 집어넣을수 없다?  


안되겠음. 새로운 예제 보고 다시 시작.

mtcars %>% map_dbl(sum)


chickwts %>% 
     split(.$feed) %>%
     map_dbl(sum)

Error in FUN(X[[i]], ...) : 
  only defined on a data frame with all numeric-alike variables


chickwts %>% map_dbl(sum)
Error in Summary.factor(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L,  : 
  요인(factors)에 대하여 의미있는 ‘sum’가 아닙니다.

# chickwts 의 feed 가 factor 라 sum 을 할 수 없다고 나는 에러임.  
# chickwts[,1] %>% map_dbl(sum) 하면 에러는 안나지만 원하는 결과가 아님.
 
 
chickwts %>% 
     split(.$feed)   %>% 
     map_df(.$weight)
Error: Can't convert NULL to function  

chickwts %>% 
     split(.$feed)   %>% 
     map_df(~sum(.$weight))
 
드디어 나왔습니다.

# A tibble: 1 x 6
  casein horsebean linseed meatmeal soybean sunflower
   <dbl>     <dbl>   <dbl>    <dbl>   <dbl>     <dbl>
1   3883      1602    2625     3046    3450      3947