【问题标题】:How to loop through values in R using subsets and logical statements?如何使用子集和逻辑语句遍历 R 中的值?
【发布时间】:2015-06-16 13:57:16
【问题描述】:

我正在尝试通过 ID 值和特定条件(如下指定)将我的数据集 (a) 中的硫酸盐和硝酸盐值关联起来。数据集包含三列(ID、硫酸盐、硝酸盐)。该代码在我单独运行每个 ID 值时有效,但现在我试图设置一个循环来遍历所有 ID 值,然后按 ID 值将所有相关性打印到单个向量中。循环没有打印出相关值,因为我确定我没有正确保存它们。如何修改下面的代码以根据每个 ID 值打印出相关值向量?

for (i in 1:5) {
    if (a$ID==i && length(a$ID==i) > 10) {
        cor(a$sulfate[a$ID==i], a$nitrate[a$ID==i])
    }
}

【问题讨论】:

  • 欢迎来到 SO。请包括MVCE。它将帮助人们回答您的问题。具体来说,请包含模拟数据集或使用 R 的内置数据集之一来复制您的问题。
  • 不要为此使用for 循环。寻找实现"split-apply-combine" approach的函数。

标签: r subset logical-operators


【解决方案1】:

试试吧:

res <- c()
for(i in 1:5) {
  res[i] <- cor(a$sulfate[a$ID==i], a$nitrate[a$ID==i])
}
res

说明

#Example data frame
df <- data.frame(ID = c(1, 1, 2, 2), sulfate = c(4, 3, 5, 1), nitrate = c(10,8, 2, 4), stringsAsFactors=F)
df
  ID sulfate nitrate
1  1       4      10
2  1       3       8
3  2       5       2
4  2       1       4

我们尝试进行逻辑测试。如果 ID 等于 1,则返回 'yes' 的输出:

if(a$ID==1) 'yes'
[1] "yes"
Warning message:
In if (a$ID == 1) "yes" :
  the condition has length > 1 and only the first element will be used

我们得到“是”的结果,但我们也得到一个警告。因为:

a$ID==1
[1]  TRUE  TRUE FALSE FALSE

测试检查a$ID 的每个元素是否等于1。这是if 语句的问题。 R 如何知道要使用哪个 TRUEFALSE 值进行测试?所以它只使用第一个。

在您的代码中,您在 if 语句中传递了类似的向量。您希望 if 语句返回一个值 TRUEFALSE。或者一起避免。

矢量化

随着您的进步,您可以通过矢量化函数调用来避免这种循环。

sapply(split(a, a$ID), function(x) cor(x['sulfate'], x['nitrate']))
 1  2 
 1 -1 

一些 R 用户编写了很棒的包来处理这些类型的问题。您将需要dplyrdata.table。这里有两个快速的替代方案。

library(dplyr)
a %>%
  group_by(ID) %>%
  summarize(Cor =cor(sulfate, nitrate))
Source: local data table [2 x 2]

  ID Cor
1  1   1
2  2  -1

library(data.table)
setDT(a)[, .(cor(sulfate, nitrate)), ID]
   ID V1
1:  1  1
2:  2 -1

【讨论】:

    猜你喜欢
    • 2021-10-21
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多