【问题标题】:Complex If Else Statement in For Loop in R Warning MessageR 警告消息中 For 循环中的复杂 If Else 语句
【发布时间】:2020-05-03 22:49:25
【问题描述】:

我为我的数据集和 2 个空向量创建了一个包含许多 if else 语句的 for 循环。但是,我收到一条警告消息:

在 closenessSupport[i]

我只是想知道如何解决这个向量长度问题,因为我认为它搞乱了我寻找 2 列平均值的意图。任何帮助表示赞赏。

【问题讨论】:

  • 请使用dput 添加数据并显示相同的预期输出。请阅读有关how to ask a good question 的信息以及如何提供reproducible example
  • 感谢您的评论。我已经使帖子更加清晰,并为我以前的一个向量提供了数据集和原始代码。如果还有什么我可以做的,请告诉我。
  • 链接说我拒绝访问。此外,最好使用dput 在帖子中添加数据。如果数据很大,请使用dput(head(df, 10))。还显示共享数据的预期输出。

标签: r rstudio


【解决方案1】:

哇,对我来说太多了我的。但是有一些轻推的答案。在这种情况下,您绝对不希望对数据框的所有行进行 for 循环。 r 已针对列进行了优化。我不完全确定我理解你所有的条件,但很可能dplyr::case_when 会很好地为你服务。

我抓取了您的数据并dputted 仅前 20 行。然后我写了一个mutatecase_when,它产生了一个朝向closenessSupport 的开始。这就是你要做的事情吗?

在您的额外输入后修改只是感兴趣的列

# https://stackoverflow.com/questions/61582653
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union
seniored <- structure(list(id = 1:20,
                           age = c(17L, 16L, 17L, 16L, 17L, 18L,
                                    17L, 17L, 18L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 16L, 17L, 16L,
                                    18L),
                           higherEd = structure(c(1L, 5L, 1L, 1L, 3L, 1L, 2L, 2L,
                                                  5L, 5L, 3L, 4L, 3L, 2L, 5L, 3L, 4L, 5L, 1L, 1L), .Label = c("2-year",
                                                                                                                                       "4-year", "None", "Other", "Vocational"), class = "factor"),
                           riskGroup = structure(c(2L, 2L, 2L, 2L, 2L, 1L, 2L, 1L, 3L,
                                                   1L, 3L, 3L, 2L, 1L, 3L, 2L, 2L, 3L, 1L, 3L), .Label = c("High",
                                                                                                           "Low", "Medium"), class = "factor"),
                           GPA = c(3.169, 2.703,
                                                                                                                                                        3.225, 2.488, 2.618, 2.928, 3.176, 3.256, 3.48, 3.244, 3.265,
                                                                                                                                                        3.4, 3.109, 3.513, 3.102, 2.656, 2.853, 3.046, 2.304, 3.473
                                                                                                           ),
                           closenessFriends = c(7L, 7L, 7L, 8L, NA, NA, NA, 6L, 7L,
                                                                                                                                   NA, 5L, 6L, 3L, 1L, 1L, NA, 8L, 2L, NA, 8L),
                           closenessMentors = c(6L,
                                                                                                                                                                                                     NA, 5L, NA, 5L, 4L, 8L, 6L, 4L, 5L, 4L, 4L, 4L, 5L, 5L, 5L,
                                                                                                                                                                                                     3L, 4L, NA, 5L),
                           numSupportSources = c(2L, 1L, 2L, 1L, 1L,
                                                                                                                                                                                                                                            1L, 1L, 2L, 2L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 2L, 2L, 0L, 2L
                                                                                                                                                                                                     )), row.names = c(NA, 20L), class = "data.frame")
seniored %>%
  mutate(
    closenessSupport = case_when(
      numSupportSources == 1 & !is.na(closenessFriends) ~ as.numeric(closenessFriends),
      numSupportSources == 1 & !is.na(closenessMentors) ~ as.numeric(closenessMentors),
      numSupportSources == 2 ~ (closenessFriends + closenessMentors)/2,
      numSupportSources == 0 ~ NA_real_),
    supportType = case_when(
      numSupportSources == 1 & !is.na(closenessFriends) ~ "FriendOnly",
      numSupportSources == 1 & !is.na(closenessMentors) ~ "MentorOnly",
      numSupportSources == 2 ~ "Both",
      numSupportSources == 0 ~ "Neither"
    )
  ) %>%
  select(numSupportSources, closenessFriends, closenessMentors, closenessSupport, supportType)
#>    numSupportSources closenessFriends closenessMentors closenessSupport
#> 1                  2                7                6              6.5
#> 2                  1                7               NA              7.0
#> 3                  2                7                5              6.0
#> 4                  1                8               NA              8.0
#> 5                  1               NA                5              5.0
#> 6                  1               NA                4              4.0
#> 7                  1               NA                8              8.0
#> 8                  2                6                6              6.0
#> 9                  2                7                4              5.5
#> 10                 1               NA                5              5.0
#> 11                 2                5                4              4.5
#> 12                 2                6                4              5.0
#> 13                 2                3                4              3.5
#> 14                 2                1                5              3.0
#> 15                 2                1                5              3.0
#> 16                 1               NA                5              5.0
#> 17                 2                8                3              5.5
#> 18                 2                2                4              3.0
#> 19                 0               NA               NA               NA
#> 20                 2                8                5              6.5
#>    supportType
#> 1         Both
#> 2   FriendOnly
#> 3         Both
#> 4   FriendOnly
#> 5   MentorOnly
#> 6   MentorOnly
#> 7   MentorOnly
#> 8         Both
#> 9         Both
#> 10  MentorOnly
#> 11        Both
#> 12        Both
#> 13        Both
#> 14        Both
#> 15        Both
#> 16  MentorOnly
#> 17        Both
#> 18        Both
#> 19     Neither
#> 20        Both

reprex package (v0.3.0) 于 2020 年 5 月 4 日创建

【讨论】:

  • 不完全是我想要的,但我非常感谢预期的帮助!我能够写出几乎所有的代码,但我只是收到一个警告,我的一个空向量的长度与我的两列的平均值不同。
  • 不客气。通过坚持循环数据框的行,您确实在与R 的优势作斗争。我可以提供更多帮助,但我有几个问题,numSupportSources 等于 1 时会发生什么?
  • 因此,由于我输入的标准和 else 语句,如果 numSupportSources 为 1,那么它要么是朋友,要么是导师。但是,我已经编码,如果不是2并且朋友支持为1,则来源支持来源是朋友。因此,默认情况下,如果 numSupportSources 为 1 而friendSupport 不是 1,则支持源是通过排除所有其他可能性的导师(这是最后一个 else 语句)
  • 我看到的数据没有friendSupport栏,这是从哪里来的?
  • friendsupport 是我之前制作的向量。朋友支持
【解决方案2】:

请接受正确答案之一

你昨天问过你的循环有什么问题。我今天看了。问题是在循环内运行rowwise。它已经基于行,因此在遍历行的 for 循环中运行它必然会导致问题。

我还为您的数据制作了一个具有代表性值的示例数据集。可能对您当前的数据无关紧要,但 for 循环会慢得多。在 20,000 行的情况下,for 循环需要 1.4 秒。 dplyr 解决方案 11 毫秒。

# build a reproducible dataset assume valid scores 1 - 8
# we'll make 9's equal to NA

set.seed(2020)
a <- sample(1:9, 20000, replace = TRUE)
a[a == 9] <- NA
set.seed(2021)
b <- sample(1:9, 20000, replace = TRUE)
b[b == 9] <- NA

seniorEdPlans2 <- data.frame(closenessFriends = a,
                              closenessMentors = b)

# use apply to calculate numSupportSources
seniorEdPlans2$numSupportSources <- apply(seniorEdPlans2, 
                                          1, 
                                          function(x) sum(!is.na(x))
                                          )

# head(seniorEdPlans2, 50) # close enough

# this was the source of your error message it's already
# row based so can't put it in a for loop
seniorEdPlans2$closenessSupport <- rowMeans(seniorEdPlans2[c('closenessFriends', 'closenessMentors')], 
                                           na.rm = TRUE)

# your for loop
for (i in 1:nrow(seniorEdPlans2)) {
  if (seniorEdPlans2$numSupportSources[i] == 2) {
    seniorEdPlans2$supportType[i] <- "Both"
  } else if (seniorEdPlans2$numSupportSources[i] == 0) {
    seniorEdPlans2$supportType[i] <- "Neither"
  } else if (!is.na(seniorEdPlans2$closenessFriends[i])) {
    seniorEdPlans2$supportType[i] <- "FriendOnly"
  } else {
    seniorEdPlans2$supportType[i] <- "MentorOnly"
  }
}

# head(seniorEdPlans2, 50)

reprex package (v0.3.0) 于 2020 年 5 月 5 日创建

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    相关资源
    最近更新 更多