首页 > 解决方案 > 在 R 中创建一个简单的 for 循环

问题描述

我有一个名为“Volume”的小标题,其中存储了一些数据(10 列 - 前 2 列是字符,30 行)。现在我想计算与我的 tibble 的第 3 列相对应的每一列的相对体积。我目前的解决方案如下所示:

rel.Volume_unmod = tibble(
            "Volume_OD" = Volume[[3]] / Volume[[3]],
            "Volume_Imp" = Volume[[4]] / Volume[[3]],
            "Volume_OD_1" = Volume[[5]] / Volume[[3]],
            "Volume_WS_1" = Volume[[6]] / Volume[[3]],
            "Volume_OD_2"  = Volume[[7]] / Volume[[3]],
            "Volume_WS_2" = Volume[[8]] / Volume[[3]], 
            "Volume_OD_3" = Volume[[9]] / Volume[[3]],
            "Volume_WS_3" = Volume[[10]] / Volume[[3]])
rel.Volume_unmod 

我想保留小标题结构和标签。我确信对此有更好的解决方案,但我对 R 相对较新,所以这对我来说并不明显。我尝试的是这样的,但我实际上无法运行它:

rel.Volume = NULL
for(i in Volume[,3:10]){

rel.Volume[i] = tibble(Volume = Volume[[i]] / Volume[[3]])
}

标签: rfor-loop

解决方案


样机数据

由于您没有提供一些数据,我按照您提供的描述创建了一些模型数据。这里:

set.seed(1)
Volume <- data.frame(ID = sample(letters, 30, TRUE),
                     GR = sample(LETTERS, 30, TRUE))
Volume[3:10] <- rnorm(30*8)

使用 Dplyr 的解决方案

library(dplyr)

# rename columns [brute force]
cols <- c("Volume_OD","Volume_Imp","Volume_OD_1","Volume_WS_1","Volume_OD_2","Volume_WS_2","Volume_OD_3","Volume_WS_3")
colnames(Volume)[3:10] <- cols

# divide by Volumn_OD
rel.Volume_unmod <- Volume %>% 
  mutate(across(all_of(cols), ~ . / Volume_OD))

# result
rel.Volume_unmod

解释

  • 我不知道你的专栏名称。这些名称可能与您打算在其中创建的列的名称相对应rel.Volume_unmod。无论如何,为了避免任何问题,我重命名了这些列(有点残忍)。如果你愿意,你可以这样做dplyr::rename
  • 有很多方法可以选择您想要的列mutatemutate是一个动词dplyr,允许您创建新列或对列执行操作或功能。
  • across是来自的副词dplyr。让我们通过说它是一个允许您在多个列上执行函数的函数来简化。在这种情况下,我想除以Volum_OD
  • ~是一种tidyverse创建匿名函数的方法。~ . / Volum_OD相当于function(x) x / Volumn_OD
  • all_of是必要的,因为在这种特定情况下,我提供across了一个字符向量。没有它,它无论如何都会工作,但你会收到一个警告,因为它是模棱两可的,并且在相同的情况下它可能会不正确地工作。

更多信息

查看这本书以了解更多关于数据操作的信息tidyverse(这dplyr是其中的一部分)。


Base-R 解决方案

rel.Volume_unmod <- Volume

# rename columns
cols <- c("Volume_OD","Volume_Imp","Volume_OD_1","Volume_WS_1","Volume_OD_2","Volume_WS_2","Volume_OD_3","Volume_WS_3")
colnames(rel.Volume_unmod)[3:10] <- cols

# divide by columns 3
rel.Volume_unmod[3:10] <- lapply(rel.Volume_unmod[3:10], `/`, rel.Volume_unmod[3])
rel.Volume_unmod

解释

  • lapply是一个基本的 R 函数,允许您将函数应用于列表或“可列出”对象的每个项目。
  • 在这种情况下rel.Volume_unmod是一个可列出的对象:一个数据框只是一个具有相同长度的向量列表。因此,lapply一次取一列 [= 一项] 并应用一个函数。
  • 功能是/。你通常看到/这样使用: A / B,但实际上/是一个 Primitive 函数。你可以这样写同样的东西:
 `/`(A, B) # same as A / B
  • lapply可以提供附加参数,这些参数直接传递给应用于列表的函数(在本例中/)。因此,我们将其写rel.Volume_unmod[3]为附加参数。
  • lapply总是返回一个列表。但是,由于我们将 lapply 的结果分配给“数据框的一部分”,我们将只编辑数据框的列,因此,我们将拥有一个数据框而不是列表。让我以更技术性的方式重新表述。分配rel.Volume_unmod[3:10] <- lapply(...)时,您不只是将列表分配给rel.Volume_unmod[3:10]. 从技术上讲,您正在使用此分配功能:[<-. 这是一个允许编辑列表/向量/数据框中的项目的功能。具体来说,[<-允许您在不修改列表/向量/数据框的属性的情况下分配新项目。正如我之前所说,数据框只是具有特定属性的列表。然后,当您使用[<-时修改列,但保持属性(在本例中为类 data.frame)不变。这就是魔法起作用的原因。

推荐阅读