r - 在 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]])
}
解决方案
样机数据
由于您没有提供一些数据,我按照您提供的描述创建了一些模型数据。这里:
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
。 - 有很多方法可以选择您想要的列
mutate
。mutate
是一个动词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)不变。这就是魔法起作用的原因。
推荐阅读
- nlp - 如何通过爬取整个网站来选择与我的句子相似的句子?
- dart - Shared Preference Dart - InternalLinkedHashMap' 不是“Map”类型的子类型
- html - 尝试创建一个自动完成 URL 的表单
- aix - 当我的应用程序从 AIX6.1 执行简单的脚本文件时,无法得到结果。请参阅标准错误。如何正确检查?
- xamarin - 从 Xamarin.UITest 运行应用程序时,NSUserDefaults plist 文件被删除并且不再创建
- python - Python:如何从用户那里获取多个值?
- c++ - wxWidgets - 在 OS X 上阻止窗口模式对话框
- ruby-on-rails - Devise & Google OAuth2:无法从请求中确定客户端 ID
- php - whereBetween 和 orWhere 获取日期范围内的数据
- react-native - 反应本机按钮对齐问题