简体   繁体   中英

Is there any way to combine two different functions to one function in R?

I have two different R functions (myDat and loading). Is there any way to combine these two functions to one function in R?

myDat <- function(filename) {
   dat <-readModels(filename, what = "parameters")$parameters  
   dat <- filter(as.data.frame(dat$unstandardized), grepl("BY|Intercepts", paramHeader))

   return(dat)
}

dat2 <- myDat("cfa.out")

loading <- function(loading) {
  loading <- dat2 %>% 
  filter(grepl("BY", paramHeader)) %>% 
  select(c(param, est)) %>% 
  separate(param, c("loading","time")) %>%
  mutate(time = paste0('time',time)) %>% 
  spread(loading, est)

  return(loading)
}

loading(dat2)

For future reference you perhaps could have supplied some example data in order to showcase the problem. As i read your question, you're looking for a way to compose two functions (ie h(x) = g(f(x)) . This can be done as follows:

myDat <- function(filename) {
  dat <- readModels(filename, what = "parameters")$parameters  
  dat <- filter(as.data.frame(dat$unstandardized), 
                grepl("BY|Intercepts", paramHeader))
  return(dat)
}

loading <- function(data) {
  data %>% 
    filter(grepl("BY", paramHeader)) %>% 
    select(c(param, est)) %>% 
    separate(param, c("loading","time")) %>%
    mutate(time = paste0('time',time)) %>% 
    spread(loading, est)
}

combined <- purrr::compose(loading, myDat)

Created on 2020-01-27 by the reprex package (v0.3.0)

We can have everything in single pipe. After extracting the 'parameters', pull the 'unstandardized', convert to data.frame , then filter the 'paramHeader` where the values are 'BY' or 'Intercepts', and combine with the rest of the pipe from the second function

library(dplyr)
library(stringr)
library(tidyr)
loadingNew <- function(filename) {
   readModels(filename, what = "parameters")$parameters  %>%
    pull('unstandardized') %>%
    as.data.frame %>%        
    filter(str_detect(paramHeader, "BY|Intercepts")) %>%   # not clear about two filter
    filter(grepl("BY", paramHeader)) %>% 
    select(param, est) %>% 
    separate(param, c("loading","time")) %>%
    mutate(time = str_c('time',time)) %>% 
    spread(loading, est)
    # or use pivot_wider
    #pivot_wider(names_from = loading, values_from = est)


}

loadingNew("cfa.out")

Thank you so much for all the helps. It was really helpful. I finally made a function that I wanted based on you guys' comments and suggestions.

MIEstimate <- function(x,n) {

 dat <-readModels(x, what = "parameters")$parameters
 dat <- filter(as.data.frame(dat$unstandardized), grepl("BY|Intercepts", paramHeader))

 if(n == 1) { 
  # loading
 loading <- dat %>% 
  filter(grepl("BY", paramHeader)) %>% 
  select(c(param, est)) %>% 
  separate(param, c("loading","time")) %>%
  mutate(time = paste0('time',time)) %>% 
  # spread(loading, est)
  pivot_wider(names_from = "loading",values_from = "est")
return(loading)

} else if(n == 2) {
# intercepts
intercept <- dat %>% 
  filter(grepl("Intercepts", paramHeader)) %>% 
  select(c(param, est)) %>% 
  separate(param, c("intercept","time")) %>%
  mutate(time = paste0('time',time)) %>% 
  # spread(intercept, est)
  pivot_wider(names_from = "intercept",values_from = "est")
return(intercept)
  }
}

MIEstimate("cfa.out", 1)
MIEstimate("cfametric.out", 2)

one thing though.... when I used spread() function, the final table time order is like this- not by small to larger time V1 V2 1 time133 1 1.038 2 time175 1 0.988 3 time19 1 0.954 4 time224 1 1.005 5 time29 1 0.974 6 time39 1 1.032 7 time5 1 0.995 8 time51 1 0.998 9 time61 1 0.987 10 time75 1 0.992 11 time91 1 0.987

but pivot_wider() works properly. Anyone knows why?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM