【问题标题】:R - Write conditional statement based on any value in a vectorR - 根据向量中的任何值编写条件语句
【发布时间】:2019-03-09 00:07:15
【问题描述】:

我正在尝试编写一个条件语句,该语句将检查向量中的任何值是否满足条件,然后根据该条件写入结果。在下面的示例中,我知道 c2 的总和远小于其他列,但在我的实际数据中,我不知道哪一列的总和更小。我想检查 csums 向量中的任何值是否小于 0.1,如果是,则将列索引写入数据框。此外,在某些情况下,会有两列低于 0.1,因此我需要将两列索引都写入数据框。

c1 <- runif(16,.3,.6)
c2 <- c(.01,.01,.01,.01,rep(.00,12))
c3 <- runif(16,.3,.6)
c4 <- runif(16,.3,.6)
c5 <- runif(16,.3,.6)
test.mat1 <- cbind(c1,c2,c3,c4,c5)
csums1 <- colSums(test.mat1)
csums1
      c1       c2       c3       c4       c5 
7.279773 0.040000 6.986803 7.200409 6.867637

c6 <- runif(16,.3,.6)
c7 <- runif(16,.3,.6)
c8 <- c(.01,.01,.01,.01,rep(.00,12))
c9 <- c(.01,.01,.01,.01,rep(.00,12))
c10 <- runif(16,.3,.6)
test.mat2 <- cbind(c6,c7,c8,c9,c10)
csums2 <- colSums(test.mat2)
csums2
      c6       c7       c8       c9      c10 
7.198180 7.449324 0.040000 0.040000 8.172110 

结果示例如下所示:

result <- matrix(c(2,0,3,4),nrow=2,byrow=T)
result
     [,1] [,2]
[1,]    2    0
[2,]    3    4

第 1 行记录第 2 列的总和小于 0.1,第 2 行记录列表中下一个数据框中的第 3 列和第 4 列的总和小于 0.1。我的实际数据是一个包含几千个数据框的列表,结果数据框继续我的列表的总长度。我计划将此条件语句嵌入到循环中以遍历每个列表元素。

【问题讨论】:

  • 你需要的主要是which(csums&lt;0.1)。我会在一分钟内发布完整的答案。
  • 调用 RNG 时,您应该调用 set.seed() 来启动脚本。

标签: r conditional


【解决方案1】:

这是一个将您提供的test.mat1test.mat2 矩阵列表作为输入的解决方案:

my_list <- list(test.mat1, test.mat2)

# For each data frame in the list, compute the column sums
# and return the indices of the columns for which the sum < 0.1
res <- lapply(my_list, function(x) {
  which(colSums(x) < 0.1)
})

# Get the number of columns for each element of the list
len <- lengths(res)
if(any(len == 0)) { # in case you have no values < 0.1, put a 0
  res[which(len == 0)] <- 0
}

# Get your result:
result <- do.call("rbind", res)

# replace duplicated values by 0:
result[t(apply(result, 1, duplicated))] <- 0

【讨论】:

  • 当我使用我的实际数据代替示例列表时,我收到错误消息“[[&lt;-(*tmp*, which(len == 0), value = 0) 中的错误:递归索引在级别 2 失败”。我的实际列表和示例之间的唯一区别是我的实际列表是数据框列表而不是矩阵。这会导致问题吗?另外,我确实需要索引为零而不是重复。我该怎么做呢?
  • 我编辑了我的答案(最后两行)以将重复值替换为 0。但是,将 test.mat1 和 test.mat2 转换为数据框时,我无法重现您的错误。你有更多关于这个问题的信息吗?
  • 它在我测试列表的特定部分(例如,2916 个元素中的 10 个)时有效,但不是全部。问题是否来自某些列表元素没有任何满足条件的列总和?在这种情况下,我希望它读取 0,但这是我可以识别的列表元素之间的唯一区别。
  • 我发现了问题。当超过 1 个数据框不满足条件时会发生这种情况。我编辑了我的答案(res[which(len == 0)] 替换了res[[which(len == 0)]])。希望这会奏效!
【解决方案2】:

示例数据:

set.seed(1234)
df1 <- data.frame(
    c1 = runif(16,.3,.6),
    c2 = c(.01,.01,.01,.01,rep(.00,12)),
    c3 = runif(16,.3,.6),
    c4 = runif(16,.3,.6),
    c5 = runif(16,.3,.6)
)

df2 <- data.frame(
    c6  = runif(16,.3,.6),
    c7  = runif(16,.3,.6),
    c8  = c(.01,.01,.01,.01,rep(.00,12)),
    c9  = c(.01,.01,.01,.01,rep(.00,12)),
    c10 = runif(16,.3,.6)
)

创建要使用的数据框名称的向量

vec_of_df_names <- c("df1", "df2")

循环遍历数据帧:

res_mat <- matrix(0, nrow=2, ncol=5)
for(i in seq_along(vec_of_df_names)) {
    res <- which(colSums(get(vec_of_df_names[i])) < 0.1)
    if(length(res)>0) res_mat[i, seq_along(res)] <- res
}
res_mat

【讨论】:

  • 感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-03
  • 2021-09-18
相关资源
最近更新 更多