【问题标题】:for-loop or create functions to create matrix (or dataframe) and rename columnsfor-loop 或创建函数来创建矩阵(或数据框)和重命名列
【发布时间】:2021-01-21 20:01:14
【问题描述】:

我试图生成几个新矩阵,并使用相同的操作但不同的变量值重命名列和行。以下是我以缓慢的方式编写的代码,我尝试使用 for-loop 和函数来执行此操作但找不到正确的方法。

m0 <- 100
N <- 1
CS <- 10.141 
S <- seq (7.72,12.56,0.807)
t <- 15 

per3 <- matrix(nrow = length(S)*N, ncol = t+1)
for (i in 1:dim(per3)[1]) {
  for (j in 1:t+1){
    per3 [,1] <- replicate (n = N, seq (7.72,12.56,0.807))
    per3 [i,j] <- round (abs (rnorm (1, mean = mean(per3[i,1]), sd = 0.2)),digits=3)
  }}
colnames(per3) <- c('physical','t1','t2','t3','t4','t5','t6','t7','t8','t9','t10','t11','t12','t13','t14','t15')
rownames(per3) <- c('S1','S2','S3','CS+','S5','S6')
per3 <- per3 [,-1]

per3_d = matrix(nrow = length(S)*N, ncol = t)
for (i in 1:dim(per3)[1]){
  for (j in 1:t){
    per3_d [i,j] <- abs (per3 [i,j] - 10.141) 
  }
}

g31 <- round (m0 * exp (-0.2 * per3_d),digits = 3)
g32 <- round (m0 * exp (-0.5 * per3_d),digits = 3)
g33 <- round (m0 * exp (-0.9 * per3_d),digits = 3)
g34 <- round (m0 * exp (-1.5 * per3_d),digits = 3)
g35 <- round (m0 * exp (-2 * per3_d),digits = 3)
colnames(g31) <- c('t1','t2','t3','t4','t5','t6','t7','t8','t9','t10','t11','t12','t13','t14','t15')
colnames(g32) <- c('t1','t2','t3','t4','t5','t6','t7','t8','t9','t10','t11','t12','t13','t14','t15')
colnames(g33) <- c('t1','t2','t3','t4','t5','t6','t7','t8','t9','t10','t11','t12','t13','t14','t15')
colnames(g34) <- c('t1','t2','t3','t4','t5','t6','t7','t8','t9','t10','t11','t12','t13','t14','t15')
colnames(g35) <- c('t1','t2','t3','t4','t5','t6','t7','t8','t9','t10','t11','t12','t13','t14','t15')

同样的问题,我需要将 g31,g32,g33,g34,g35 作为数据帧,我可以使用 for 循环来执行此操作而不是重复操作吗?

sub1pd<-as.data.frame (per_d)
sub1p<-as.data.frame(per)
sub1g11 <- as.data.frame(g11)
sub1g12 <- as.data.frame(g12)
sub1g13 <- as.data.frame(g13)
sub1g14 <- as.data.frame(g14)
sub1g15 <- as.data.frame(g15)

非常感谢您的帮助!


我尝试使用与 per 和 per_d 相同的方法,其中我再次具有相同的结构但不同的 sd 值。但是,我不确定如何执行此操作,因为我有不同的步骤来为第一列生成数据,其余的为每个 per 和 per_d 生成数据。

sd <- c(0.2, 0.5, 0.9)
names(sd) <- paste("per", seq_along(sd), sep = "") 
res <- lapply(sd, function(x){ 
  per <- matrix(nrow = length(S)*N, ncol = t+1)
  for (i in 1:dim(per)[1]) {
    for (j in 1:t+1){
      per [,1] <- replicate (n = N, seq (7.72,12.56,0.807))
      per [i,j] <- round (abs (rnorm (1, mean = mean(per[i,1]), sd = x)),digits=3)
      colnames(per) <- paste(t, 1:ncol(per), sep = "")
      per <- as.data.frame (per)
    }
    }
}
)  

【问题讨论】:

  • 您能否提供m0per3_d 以便我们有一个可重现的示例?第一次猜测lapply(c(-0.2, -0.5, -0.9, - 1.5, - 2), function(x){ g &lt;- round (m0 * exp (x * per3_d),digits = 3)...
  • 是的,我刚刚用 m0 和 per3_d 编辑了我的问题。感谢您的回复!
  • 请验证您的代码是否可以运行,示例中并未定义所有变量。 S, N, t
  • 真的很抱歉,我现在已经定义了问题中的所有变量
  • 我猜for (i in 1:dim(per)[1])的部分应该是for (i in 1:dim(per3)[1])

标签: r for-loop


【解决方案1】:

在您的示例中,您正在手动迭代。这是非常低效的。简化代码的一种方法是使用for 循环进行迭代,如果您知道自己在做什么以及为什么要这样做,那么在 R 中没有任何问题(我提到这一点是因为很多人不这么认为)。但作为 R 用户,您应该熟悉 apply 系列函数,尤其是 lapply

exps <- c(-0.2, -0.5, -0.9, -1.5, - 2)
names(exps) <- paste("g3", seq_along(exps), sep = "") #name the vactor

res <- lapply(exps, function(x){ #for each x element in the exps vector perform the function
  g <- round(m0 * exp (x * per3_d), digits = 3)
  colnames(g) <- paste("t", 1:ncol(g), sep = "") #avoid typing sequences which can be generated easily
  g <- as.data.frame(g)
  g
}
)  

这样所有的数据框都将放在一个列表中,这样可以更容易地进行进一步的操作。

如果你真的需要环境中的列表元素(我非常怀疑你真的需要):

list2env(res, globalenv())

【讨论】:

  • 非常感谢您的回答。请问接下来我应该怎么做才能将它们命名为 g31,g32,g33... 并将它们作为单独的数据框?我需要先将其取消列出,对吗?
  • 您能解释一下为什么需要将它们作为单独的数据框吗?很可能这不是必需的,但我整理了答案以说明如何做到这一点。
  • 对不起,这可能是一个愚蠢的问题。我是 R 的初学者。我了解您在这里所做的是将 g31~g35 与 lapply 一起运行并将它们作为列表。我现在不确定的是,当我需要单独使用 g31~g35 进行进一步计算和绘制绘图时,我应该做什么。使用单独的数据框,我很清楚如何执行以下操作。
  • res$g31 你可以像这样获得单独的df。如果您希望它们在env() 中使用list2env(res, globalenv())
  • 我现在明白了,这真是一个愚蠢的错误。非常感谢您的耐心等待,我确实从中学到了很多东西。
猜你喜欢
  • 1970-01-01
  • 2022-11-17
  • 1970-01-01
  • 2021-12-15
  • 1970-01-01
  • 2013-03-30
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
相关资源
最近更新 更多