【问题标题】:Relating dataframes with If statements and loops将数据帧与 If 语句和循环相关联
【发布时间】:2017-01-25 22:23:18
【问题描述】:

我有以下数据框:

df1 <- data.frame(ProjectID=c(10,11,12,13),
              Value1=c(101.25,102.85,102.95,103.15),
              Value2=c(103.58,104.27,104.68,106.01))
df2 <- data.frame(ProjectID=c(10,10,11,11,11,12,13,13),
              Value3=c(98.32,102.58,99.66,103.47,105.63,105.18,102.02,104.98))

我想创建以下列df1$Value4,如果满足以下条件,则从df2$Value3拉取:

  1. ProjectIDs 必须匹配 df1 和 df2
  2. df2$Value3 必须介于 df1$Value1 和 df1$Value2 之间
  3. 如果以上2个条件都不满足,输入“”

如果可能的话,我对使用循环和 if 语句来完成这一点很感兴趣。非常感谢任何帮助。

输出应如下所示:

df1 <- data.frame(ProjectID=c(10,11,12,13),
              Value1=c(101.25,102.85,102.95,103.15),
              Value2=c(103.58,104.27,104.68,106.01),
              Value4=c(102.58,103.47,"",104.98))

【问题讨论】:

  • 看看match() 和which(),在这两者之间你应该可以尝试一些东西然后回来调整。
  • 结果中的df1$Value4应该是一个数值向量吗?

标签: r loops if-statement for-loop


【解决方案1】:

这将merge 两个data.frame 然后删除Value3 不在Value1 和Value2 之间的行。第二个merge 将添加来自df1 的不满足先前条件的行。最后最后一个命令将重命名列。

df3 <- merge(df1, df2)
df3 <- df3[df3$Value1 < df3$Value3 & df3$Value3 < df3$Value2, ]
df3 <- merge(df1, df3, all.x = TRUE)
colnames(df3)[colnames(df3) == "Value3"] <- "Value4"

df3
  ProjectID Value1 Value2 Value4
1        10 101.25 103.58 102.58
2        11 102.85 104.27 103.47
3        12 102.95 104.68     NA
4        13 103.15 106.01 104.98

【讨论】:

    【解决方案2】:

    通过循环和逻辑语句来做会使代码有点长。我确信 dplyr 语句可以缩短这个时间。此外,我不确定您打算对输出做什么,但由于“”,R 会将 Value4 字段转换为字符数据类型。如果您希望之后进行任何类型的数据操作,我建议使用 NAs 而不是“”。为此,只需在下面的代码中将“”替换为 NA。无论如何,您要查找的代码是:

    df1$Value4 <- ""
    
    for (i in 1:nrow(df1)) {
      match_df2 <- df2$Value3[df2$ProjectID == df1$ProjectID[i]]
    
      btwn <- c(df1$Value1[i], df1$Value2[i])
      btwn <- sort(btwn)
      match_v12 <- c()
      for (j in 1:length(match_df2)) {
        if (match_df2[j] >= btwn[1] & match_df2[j] <= btwn[2]) {
          match_v12 <- rbind(match_v12, match_df2[j])
        }
      }
      if (length(match_v12) == 0) {
        df1$Value4[i] <- ""
      } else {
        df1$Value4[i] <- max(match_v12)
      }
    }
    

    首先在 df1 中创建空的 Value4 字段并用空字符串填充它。第一个循环语句将遍历 df1 中的每个 projectID 并确定 df2 中 ProjectID 的匹配位置。这些匹配的位置存储在 match_df2 中。接下来,将 Value1 和 Value2 放入一个名为 btwn 的向量中以进行排序。在您给出的示例中,Value1 始终小于 Value2,但我不确定是否总是如此。

    下一个 for 循环检查匹配的 Value3 值是否介于 Value1 和 Value2 之间。如果 Value3 介于两者之间,它会将 Value3 添加到名为 match_v12 的向量中。如果为单个 ProjectID 找到多个匹配项,则我假设匹配的 Value3 的最大值。你可以把它改成你喜欢的任何东西,我只是把一些东西放下。最后,如果没有找到匹配项,则生成“”(这最后一部分是多余的,但总体而言,不错的代码)。

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 1970-01-01
      • 1970-01-01
      • 2011-09-24
      • 1970-01-01
      • 2013-01-27
      相关资源
      最近更新 更多