for 循环在 R 中起作用 [closed]

for loop to function in R [closed]

提问人:Seyma Kalay 提问时间:11/22/2021 最后编辑:Seyma Kalay 更新时间:11/23/2021 访问量:108

问:


这个问题是由一个错别字或一个无法再重现的问题引起的。虽然类似的问题可能在这里成为主题,但这个问题的解决方式不太可能帮助未来的读者。

2年前关闭。

我正在尝试将 for 循环转换为函数。预期结果是 .任何帮助将不胜感激,以获得函数格式的预期结果 ()。Summ.StatsSumm.Statsb

CN = colnames(mtcars);CN
var <- c("vs", "am")

Summ.Stats <- NULL
library(psych)

for (i in 1:(length(var))) {
  
  temp <- which(CN == var[i])
  
  aux.0 <- mtcars  %>% filter(mtcars[,temp]==0)
  aux.1 <- mtcars %>% filter(mtcars[,temp]==1)
  fname.0 <- paste0(paste(var[i], "0", sep = "_"))
  fname.1 <- paste0(paste(var[i], "1", sep = "_"))
  Summ.0 <- describe(aux.0)
  Summ.1 <- describe(aux.1)
  tab <- round(cbind(Summ.0$mean, Summ.1$mean), 4)
  rownames(tab) <- colnames(aux.0)
  colnames(tab) <- c(fname.0, fname.1)
  Summ.Stats [[i]] <- tab
}
Summ.Stats #EXPECTED OUTCOME

我尝试的是以下内容;

Summ.Stats <- NULL
my.function <- function(var, df){
  
  df <- df[, !sapply(df, is.character)]#REMOVE THE CHARACTER COLUMNS
  CN = colnames(df)  
  
  for (i in 1:length(var)) {
    temp <- which(CN == var[i])
    #
    res <- split(df, df[,temp])
    names(res) <- paste(var[i], names(res), sep = ".") 
    return(res) }
    
    for (j in 1:length(res)){
      tab <- describe(res[[j]]) #here the mean of res[[1]] and res[[2]] should be saved
      Summ.Stats [[j]] <- tab
      return(Summ.Stats)
    }
  }

b <- my.function(var, mtcars);b #only shows vs.0 and vs.1
R 函数 for 循环 数据操作

评论

1赞 Limey 11/22/2021
将您的退货报表移出循环。在 mkoment,您从第一个循环的第一次迭代中返回。formy.functionfor

答:

0赞 Quixotic22 11/22/2021 #1

我在这里很懒惰,但乍一看可能是因为你写了退货的地方,请尝试:

my.function <- function(var, df){
  
  df <- df[, !sapply(df, is.character)]#REMOVE THE CHARACTER COLUMNS
  CN = colnames(df)  
  
  for (i in 1:length(var)) {
    temp <- which(CN == var[i])
    #
    res <- split(df, df[,temp])
    names(res) <- paste(var[i], names(res), sep = ".") 
    }
    
    for (j in 1:length(res)){
      tab <- describe(res[[j]]) #here I need to save mean res[[1]] and res[[2]]
      Summ.Stats [[j]] <- tab
    } 
   return(Summ.Stats)
  }

评论

1赞 moodymudskipper 11/23/2021
恐怕这段代码还有很多问题
1赞 moodymudskipper 11/23/2021 #2

一些建议:

  • 小心在正确的位置返回,在每个 for 循环结束时返回永远不会正确
  • 试着了解你正在增长的对象,每次在循环中被新值擦除,在测试前一步之前不要对下一步进行编程res
  • 不需要时,不要在彼此之间转换数字、字符、逻辑索引
  • 当可以循环使用名称时,不要循环使用数字索引,如果可以直接循环使用项目,则不要循环使用名称。
  • 尽可能学会使用而不是循环lapplyfor
  • 在您的函数中使用来了解您在做什么。browser()
  • 如果可能的话,把数据参数放在第一位(我在下面不这样做来重现你请求的输出)
  • 玩得开心:)

我想你想要以下内容

my.function <- function(var, df){
  df <- Filter(is.numeric, df) 
  lapply(var, function(nm) {
    # browser() # uncomment, run and print objects to understand what these steps do
    split_data <- split(df, df[[nm]])
    cols <- lapply(split_data, function(x) psych::describe(x)["mean"])
    df <- do.call(cbind, cols)
    names(df) <- paste(nm, names(split_data), sep = ".")
    df
  })
}
my.function(c("vs", "am"), mtcars)
#> [[1]]
#>             vs.0       vs.1
#> mpg   16.6166667  24.557143
#> cyl    7.4444444   4.571429
#> disp 307.1500000 132.457143
#> hp   189.7222222  91.357143
#> drat   3.3922222   3.859286
#> wt     3.6885556   2.611286
#> qsec  16.6938889  19.333571
#> vs     0.0000000   1.000000
#> am     0.3333333   0.500000
#> gear   3.5555556   3.857143
#> carb   3.6111111   1.785714
#> 
#> [[2]]
#>             am.0        am.1
#> mpg   17.1473684  24.3923077
#> cyl    6.9473684   5.0769231
#> disp 290.3789474 143.5307692
#> hp   160.2631579 126.8461538
#> drat   3.2863158   4.0500000
#> wt     3.7688947   2.4110000
#> qsec  18.1831579  17.3600000
#> vs     0.3684211   0.5384615
#> am     0.0000000   1.0000000
#> gear   3.2105263   4.3846154
#> carb   2.7368421   2.9230769

reprex 包 (v2.0.1) 于 2021-11-22 创建

1赞 Donald Seinen 11/23/2021 #3

还有另一种方法 - 使用一些点并完全避免包装。psych

data <- mtcars

b <- function(df, ...){
  m <- function(y, z) df[df[[y]] == z,] |> colMeans()
  args <- as.list(match.call()[-c(1L, 2L)])
  lapply(args, \(.){
    cbind(m(., 0), m(., 1)) |>  # if you want a data.frame use cbind.data.frame instead
      (\(x) {colnames(x) <- paste0(c(., .), c("_1", "_2")) ; x})()
  }) |>
    lapply(round, 4)
}
b(data, vs, am)

#> [[1]]
#>          vs_1     vs_2
#> mpg   16.6167  24.5571
#> cyl    7.4444   4.5714
#> disp 307.1500 132.4571
#> hp   189.7222  91.3571
#> drat   3.3922   3.8593
#> wt     3.6886   2.6113
#> qsec  16.6939  19.3336
#> vs     0.0000   1.0000
#> am     0.3333   0.5000
#> gear   3.5556   3.8571
#> carb   3.6111   1.7857
#> 
#> [[2]]
#>          am_1     am_2
#> mpg   17.1474  24.3923
#> cyl    6.9474   5.0769
#> disp 290.3789 143.5308
#> hp   160.2632 126.8462
#> drat   3.2863   4.0500
#> wt     3.7689   2.4110
#> qsec  18.1832  17.3600
#> vs     0.3684   0.5385
#> am     0.0000   1.0000
#> gear   3.2105   4.3846
#> carb   2.7368   2.9231

解释 - 在检查时,它会运行一堆我们在输出中不需要的函数。相反,我们可以做的是制作一个辅助函数,该函数对数据进行子集并直接计算列均值,从而保留名称。要处理任意数量的变量,通常最好使用列表,即使用或样式方法,这样可以使语法简洁。psych::describe()mlapplypurrr::map