【问题标题】:iterating a loop to give a new value if the previous value already exists in a data frame in R如果前一个值已经存在于 R 中的数据框中,则迭代循环以提供新值
【发布时间】:2021-03-20 03:26:40
【问题描述】:

我在这里有一个包含此信息的数据框:

df <- data.frame("string1" = c("ABECDE","ABECDE","ABECDE"), 
             "string2" = c("ABCD","ABCD","ABCD"),
             "site1" = NA, "site2" = NA, "combine" = NA, "filtered" = NA)

我想编写一个代码,在字符串中选择站点 E 和 D 并将它们添加到数据框中。 如果组合已经创建,我希望它返回并选择一个新组合并再次检查,直到它得到一个尚未选择的组合。

我在下面提供了我到目前为止所做的代码,它给出了以下输出:

  string1 string2 site1 site2 combine filtered
1  ABECDE    ABCD    E3    D4    E3D4     E3D4
2  ABECDE    ABCD    E3    D4    E3D4     <NA>
3  ABECDE    ABCD    E3    D4    E3D4     <NA>

这里,E3D4 是你第一次通过函数时得到的值。 我现在希望它返回并选择下一个可能的组合: 接下来两行的 E6D4 和 D5D4 但我不知道如何正确地构造迭代。

这是我到目前为止的代码(可能有一种不太冗余的方式来编写它,但我是初学者,所以如果它过长,请见谅)

#make the columns of string1 and string2 into vectors 
string1 <- df$string1
string2 <- df$string2

#for each string in the vector check to see first if it has an E, if not, then a D
#get the output as a letter and its position (eg E3)
for (i in 1:nrow(df)){
if (grepl("E", string1[i])){
  sites1 = gregexpr('E', string1[i])
  df$site1 <- paste0(substring(string1[i], sites1[[1]][1], sites1[[1]][1]), sites1[[1]][1])
  } else if (grepl("D", string1[i])){
    sites = gregexpr('D', string1[i])
    df$site1 <- paste0(substring(string1[i], sites1[[1]][1], sites1[[1]][1]), sites1[[1]][1])
  }
}
#do the same for the second vector
for (i in 1:nrow(df)){
if (grepl("E", string2[i])){
  sites2 <- gregexpr('E', string2[i])
  df$site2 <- paste0(substring(string2[i], sites2[[1]][1], sites2[[1]][1]), sites2[[1]][1])
} else if (grepl("D", string2[i])){
  sites2 <- gregexpr('D', string2[i])
  df$site2 <- paste0(substring(string2[i], sites2[[1]][1], sites2[[1]][1]), sites2[[1]][1])
}
}
#combine the sites
df$combine <- paste0(df$site1, df$site2)

#for each row of combined sites, check to see if the value is already created
for (i in 1:nrow(df)){
  if(!df$combine[i] %in% df$filtered){
    df$filtered[i] <- df$combine[i]
  } else if(df$combine[i] %in% df$filtered){
    #go back to for loop and look for either another E in the list
    #if there is none, go to the next condition (looking for a D).
    #pick the next possible values, put them together and check again
    #do this continuously until you get a unique combine.
    #do this for string1 and then string2 (or alternating both, which ever is easier)
}
}

【问题讨论】:

    标签: r dataframe loops iteration conditional-statements


    【解决方案1】:

    也许您可以简化并尝试以下操作。

    创建一个自定义函数,它将检测字符串中“D”和“E”的所有位置。然后使用expand.grid 获取这些位置的所有组合。在您的示例数据中,这将包括位置 3、5、6 与位置 4 的组合(最后是 3 种组合:(3, 4)、(5, 4) 和 (6, 4))。

    然后,您可以通过将来自位置的字母与位置编号组合paste 来遍历这些组合中的每一个并创建所需的字符串。一个列表将保存这些结果,并在最后与rbind 组合在一起。

    还有几个问题,包括是否存在找不到“D”或“E”字母的情况。

    my_fun <- function(x) {
      p1 <- as.numeric(unlist(gregexpr(pattern = 'D|E', x[["string1"]])))
      p2 <- as.numeric(unlist(gregexpr(pattern = 'D|E', x[["string2"]])))
      cbn <- expand.grid(p1, p2)
      lst <- list()
      for (i in seq_len(nrow(cbn))) {
        site1 <- paste0(substr(x[["string1"]], cbn[i, "Var1"], cbn[i, "Var1"]), cbn[i, "Var1"])
        site2 <- paste0(substr(x[["string2"]], cbn[i, "Var2"], cbn[i, "Var2"]), cbn[i, "Var2"])
        lst[[i]] <- c(string1 = x[["string1"]], string2 = x[["string2"]], site1 = site1, site2 = site2, combine = paste0(site1, site2))
      }
      return(as.data.frame(do.call("rbind", lst)))
    }
    
    do.call(rbind, apply(df, 1, my_fun))
    

    我创建了示例数据来对此进行测试:

      string1 string2 site1 site2 combine filtered
    1  ABECDE    ABCD    NA    NA      NA       NA
    2  AABCDE    ABCE    NA    NA      NA       NA
    3  ABCDDE    ACDD    NA    NA      NA       NA
    

    这将给出以下输出:

       string1 string2 site1 site2 combine
    1   ABECDE    ABCD    E3    D4    E3D4
    2   ABECDE    ABCD    D5    D4    D5D4
    3   ABECDE    ABCD    E6    D4    E6D4
    4   AABCDE    ABCE    D5    E4    D5E4
    5   AABCDE    ABCE    E6    E4    E6E4
    6   ABCDDE    ACDD    D4    D3    D4D3
    7   ABCDDE    ACDD    D5    D3    D5D3
    8   ABCDDE    ACDD    E6    D3    E6D3
    9   ABCDDE    ACDD    D4    D4    D4D4
    10  ABCDDE    ACDD    D5    D4    D5D4
    11  ABCDDE    ACDD    E6    D4    E6D4
    

    【讨论】:

    • 感谢您的建议! expand.grid 函数非常有用。需要调整它选择字母的顺序,但这没问题 :) 而且仍然不应该有任何字符串没有我想要的字母。
    猜你喜欢
    • 1970-01-01
    • 2019-08-14
    • 1970-01-01
    • 2014-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-04
    相关资源
    最近更新 更多