【问题标题】:Detecting whether strings arise in a specific order检测字符串是否以特定顺序出现
【发布时间】:2019-10-30 17:22:00
【问题描述】:

我想计算我的学生说出 5 个特定单词和子集/过滤器的次数,这些单词以正确的顺序排列学生的回答。 正确的顺序 = 绿色、黄色、橙色、红色、黑色。 所有数据均为小写且没有标点符号:

#     Student responses
Id    Data$Colors
1     green yellow orange red black
2     yellow green orange red black
3     red violet pink black
4     purple green orange red black
5     blue pink yellow scarlet   

我的目标是:

#   Student responses
Id  Data$Colors                                Data$Count   Data$CorrOrder
1   green yellow orange red black              5            TRUE
2   yellow green orange red blacks             4            FALSE
3   red violet pink black                      2            TRUE
4   purple green orange red black              4            TRUE
5   blue pink yellow brown                     1            NA
6   green yellow orange red very red black     4*           TRUE

-1 点重复。 我已经能够通过这样做获得计数列

Data <- c("\\bgreen\\b", "\\byellow\\b", "\\borange\\b", "\\bred\\b", "\\bblack\\b")

Data$Count<- str_count(Data$Colors, paste(Data, collapse = '|'))

但是,这不会减去重复的正确颜色,例如 Id 6。

有人知道我如何生成Data$CorrOrder吗?

【问题讨论】:

    标签: r string count stringr detect


    【解决方案1】:

    使用tidyverse我们可以分别得到CountCorrOrder。为了获得Count,我们首先在空间上拆分Colors,并为每种颜色创建separate_rows,以便于比较值。然后,我们计算每个Id 中有多少unique Colors 存在于总数all_colors 中,并且由于我们想为每个重复值给出-1,我们将每个重复值减去duplicated 值的数量小组给我们总分。

    all_colors <- c("green", "yellow", "orange", "red", "black")
    library(tidyverse)
    
    df1 <- df %>%
          left_join(df %>%
                     separate_rows(Colors, sep = "\\s+") %>%
                     group_by(Id) %>%
                     summarise(count = max(sum(all_colors %in% unique(Colors)) - 
                                       sum(duplicated(Colors)), 0)))
    

    为了获得正确的顺序,我们再次将颜色分成不同的行,仅保留 all_colors 中的颜色并删除重复项并检查颜色出现的顺序是否总是增加并相应地分配逻辑 TRUE/FALSE 值.

    df1 %>%
       left_join(df1 %>%
                  separate_rows(Colors, sep = "\\s+") %>%
                  group_by(Id) %>%
                  filter(Colors %in% all_colors & !duplicated(Colors)) %>%
                  summarise(new = if (n() == 1) NA 
                  else all(diff(na.omit(match(Colors, all_colors))) > 0)))
    
    #  Id                                 Colors CorOrder Count
    #1  1          green yellow orange red black     TRUE     5
    #2  2         yellow green orange red blacks    FALSE     4
    #3  3                  red violet pink black     TRUE     2
    #4  4          purple green orange red black     TRUE     4
    #5  5                 blue pink yellow brown       NA     1
    #6  6 green yellow orange red very red black     TRUE     4
    

    【讨论】:

    • 感谢 Ronak,这很有帮助。我有几个后续问题。通过您提供的第一部分,您知道我如何确保为重复颜色给出的 -1 停止在 0 吗? (有些行以我不想要的负分结束)。在第二部分中,我收到以下消息:“$tmp, DRRecallCorrOrder, value = c(TRUE, : 替换有 3065 行,数据有 3172 ”。任何想法为什么?
    • @interestedfinnfisher 对于第一个问题,我们可以使用max 确保值停止在 0。我已经更新了答案的那部分。关于您的第二个问题,我无法重现它,所以我猜您是否有 NAColors 列中有一些空值?
    • 您好 Ronak,非常感谢您提出使用 max() 的建议,现在可以使用了。但是我在颜色列中没有任何空行/NA,我仍然无法解决预期输出和输入数据帧之间的行数不匹配的问题
    • @interestedfinnfisher 你能试试更新版本吗?我在match 之后的答案中包含了na.omit
    • 您能否通过不使用pull 而是根据ID 将摘要加入原始数据来解决可能的不匹配问题?
    【解决方案2】:

    首先,如果您将值视为ordered 因子,您可以使用is.unsorted 检查它们是否已排序,而不是排序:

    colorder <- c("green", "yellow", "orange", "red", "black")
    
    spl <- lapply(strsplit(dat$Colors, "\\s+"), ordered, levels=colorder)
    cnt <- sapply(spl, function(x) length(unique(na.omit(x))) - sum(tabulate(x) > 1) )
    cnt
    #[1] 5 4 2 4 1 4
    out <- !sapply(spl, is.unsorted, na.rm=TRUE)
    out[cnt == 1] <- NA
    out
    #[1]  TRUE FALSE  TRUE  TRUE    NA  TRUE
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-23
      • 2014-12-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多