【问题标题】:How do I create a column based on values of another using dplyr without having to write down every value?如何使用 dplyr 创建基于另一个值的列,而不必写下每个值?
【发布时间】:2020-04-15 18:28:39
【问题描述】:

有没有什么方法可以更有效地做到这一点?我想创建一个项目类型的列。每个参与者都有不同数量的项目,所以这真的很棘手。这是我的数据的一个玩具示例

structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L), condition = c("high", "high", "high", "high", "high", 
"high", "high", "high", "medium", "medium", "medium", "medium", 
"medium", "medium", "medium", "low", "low", "low", "low", "low", 
"low", "low", "low", "low", "low", "low", "low", "low", "low", 
"low", "high", "high", "high", "high", "high", "high", "high", 
"medium", "medium", "medium", "medium", "medium", "medium", "medium"
), item = c("abcde", "bcdef", "cdefgh", "defgh", "efghi", "fghijk", 
"ghijkl", "hijklm", "1234", "2345", "3456", "4567", "5678", "6789", 
"7890", "onion", "celery", "tomato", "carrot", "green bean", 
"lettuce", "garlic", "abcde", "bcdef", "cdefgh", "defgh", "efghi", 
"fghijk", "ghijkl", "hijklm", "onion", "celery", "tomato", "carrot", 
"green bean", "lettuce", "garlic", "1234", "2345", "3456", "4567", 
"5678", "6789", "7890")), row.names = c(NA, -44L), class = c("tbl_df", 
"tbl", "data.frame"))

这是我迄今为止所做的,但这是一场噩梦,因为我有一百多个不同的项目:

df$subs <- 0
df$subs[df$item=="abcde"] <- "A"
df$subs[df$item=="bcdef"] <- "A"
df$subs[df$item=="cdefg"] <- "A"
df$subs[df$item=="defgh"] <- "A"
df$subs[df$item=="efghi"] <- "A"

df$subs[df$item=="12345"] <- "B"
df$subs[df$item=="23456"] <- "B"
df$subs[df$item=="34567"] <- "B"
df$subs[df$item=="45678"] <- "B"
df$subs[df$item=="56789"] <- "B"

df$subs[df$item=="onion"] <- "C"
df$subs[df$item=="celery"] <- "C"
df$subs[df$item=="tomato"] <- "C"
df$subs[df$item=="carrot"] <- "C"
df$subs[df$item=="green bean"] <- "C"

tidyverse 有更快的方法吗?

【问题讨论】:

  • 这不使用 tidyverse,它可能仍然不是最佳解决方案,但您可以执行类似 x &lt;- c("abcde", "bcdef", "cdefg", "defgh", "efghi") 后跟 df$subs[df$item %in% x] &lt;- "A" 的操作。它至少可以让您不必为要匹配的每个值写一行。
  • 如果 item-LETTER 映射没有明确的公式,很难看出如何使用代码进行分配。如果您必须手动完成分配,则在 Excel 中完成,然后将完成的数据框导入 R 可能会更容易。对于 Excel 中的 LETTERS 列,您可以使用数据验证功能并创建允许值的列表。这将为每个单元格提供一个选择下拉菜单,以使输入更容易。此外,每次完成 LETTER 映射时,您都可以对列进行排序,以使所有尚未分配的单元格保持连续。

标签: r dplyr tidyverse


【解决方案1】:

我认为最简单的方法是使用正则表达式来简化这一点。您可以使用 tidyverse,但这不是绝对必要的。这是一个 tidyverse 示例:

library(tidyverse)
df %>% 
  mutate(subs = case_when(
    str_detect(item, "[a-m]{5}") ~ "A",
    str_detect(item, pattern = "\\d+") ~ "B",
                          TRUE ~ "C"))

这里的关键是您选择的正则表达式模式需要对您的真实数据精确。我认为这个版本适用于您包含的简单示例。另外,请注意dput 表示与提供的数据不同 - 因此我选择在第一个正则表达式模式中使用[a-m]

【讨论】:

  • 这正是我所需要的,它就像魔术一样工作,但我不知道如何使用正则表达式或如何找到它的代码。我找到了一个可能会有所启发的网站,但例如 \\d+ 对我来说没有意义。关于如何谷歌它的任何建议? “正则表达式代码”不起作用。
  • 很高兴我能帮上忙。 \\d+ 识别一位或多位数字。很抱歉,正则表达式很难掌握。这是 Rstudio 备忘单供参考 - rstudio.com/wp-content/uploads/2016/09/RegExCheatsheet.pdf - 还有这个网站,regexr.com,允许您尝试这些概念。
猜你喜欢
  • 1970-01-01
  • 2017-11-12
  • 2019-06-14
  • 2020-12-27
  • 1970-01-01
  • 2020-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多