【问题标题】:R how to extract n-grams based rowsR如何提取基于n-gram的行
【发布时间】:2019-11-01 01:36:00
【问题描述】:

我有一个数据框df:

userID Score  Task_Alpha Task_Beta Task_Charlie Task_Delta 
3108   -8.00  Easy       Easy      Easy         Easy
3207    3.00  Hard       Easy      Match        Match
3350    5.78  Hard       Easy      Hard         Hard
3961    10.00 Easy       Easy      Hard         Hard


1. userID is factor variable
2. Score is numeric
3. All the 'Task_' features are factor variables with possible values 'Hard', 'Easy', 'Match'

我想查看转换(Task_alphaTask_betaTask_CharlieTask_Delta)和分数之间可能存在的关联。

我的假设是2-grambi-gramsequence Hard Hard 可能与更高的分数相关联。但是,序列Easy Easy 将与较低的分数相关。

在这个例子中,我只考虑了2-gram。在我的实际代码中,我也想尝试更长的序列。仅供参考,您可以看到我们可以拥有的bi-grams 总数为:

Easy Hard
Hard Easy
Easy Match
Match Easy
Hard Match
Match Hard

问题:作为第一步,我需要的总体输出类似于:

Task   Task  Score 
Easy   Easy -8.00
Easy   Easy -8.00
Easy   Easy -8.00
Hard   Easy  3.00
Easy  Match  3.00
Match Match  3.00
Hard   Easy  5.78
Easy   Hard  5.78
Hard   Hard  5.78
Easy   Easy  10.00
Easy   Hard  10.00
Hard   Hard  10.00

【问题讨论】:

    标签: r nlp token sequence n-gram


    【解决方案1】:

    首先,您需要将所有因子转换为字符(否则,在下一步中,R 将使用它们的索引,而不是使用因子的值)。

    dplyr 的一个选项:

    library(dplyr)
    
    df <- df %>% mutate_if(is.factor, as.character)
    

    那么你可以这样做:

    data.frame(Task1 = c(df[, 3], df[, 4], df[, 5]),
               Task2 = c(df[, 4], df[, 5], df[, 6]),
               Score = rep(df[, 2], 3)) %>%
      arrange(Score)
    

    输出:

       Task1 Task2 Score
    1   Easy  Easy -8.00
    2   Easy  Easy -8.00
    3   Easy  Easy -8.00
    4   Hard  Easy  3.00
    5   Easy Match  3.00
    6  Match Match  3.00
    7   Hard  Easy  5.78
    8   Easy  Hard  5.78
    9   Hard  Hard  5.78
    10  Easy  Easy 10.00
    11  Easy  Hard 10.00
    12  Hard  Hard 10.00
    

    【讨论】:

    • 感谢您的解决方案。但是,它在我的原始数据集中不起作用。我收到以下错误Error in data.frame(Task1 = c(df[, 5], df[, 6], df[, 7]), Task2 = c(df[, : arguments imply differing number of rows: 708, 1180
    • 你的代码和我的不一样:你调整它以匹配你的数据还是这是一个错字?如果不是错字,您需要分享更多信息,因为代码适用于您在问题中发布的内容。因此,我们没有足够的信息来了解为什么它对您不起作用
    • 我需要调整您的代码。我的原始数据有几列和大约 200 行。
    • 好的。然后我需要有关您的数据的更多信息,以了解它为什么不起作用。
    【解决方案2】:

    我已经能够解决这个问题,如下所示:

    第 1 步: 作为第一步,我连接了这些列:

     df$all = paste(df$Task_Alpha,
                  df$Task_Beta,
                  df$Task_Charlie,
                  df$Task_Delta,
                  sep="-")
    
    userID  Score Task_Alpha Task_Beta Task_Charlie Task_Delta all
    3108   -8.00  Easy       Easy      Easy         Easy       Easy-Easy-Easy-Easy
    3207    3.00  Hard       Easy      Match        Match      Hard-Easy-Match-Match
    3350    5.78  Hard       Easy      Hard         Hard       Hard-Easy-Hard-Hard
    3961    10.00 Easy       Easy      Hard         Hard       Easy-Easy-Hard-Hard
    

    第 2 步: 作为第二步(获得更通用的解决方案),我尝试了基于n-gram 的方法。我尝试将字符串拆分为我想要的任何大小n-gram

    library(tidytext)
    library(dplyr)
    
    df = as_tibble(df)
    df_test = df %>%
       unnest_tokens(bigram, all, token = "ngrams", n = 2)
    

    这给了我输出:

    userID Score Task_*A* Task_*B* Task_*C* Task_*D* all                   bigram
    3108  -8.00  Easy     Easy     Easy     Easy     Easy-Easy-Easy-Easy   easy easy
    3108  -8.00  Easy     Easy     Easy     Easy     Easy-Easy-Easy-Easy   easy easy
    3108  -8.00  Easy     Easy     Easy     Easy     Easy-Easy-Easy-Easy   easy easy
    3207   3.00  Hard     Easy     Match    Match    Hard-Easy-Match-Match hard easy
    3207   3.00  Hard     Easy     Match    Match    Hard-Easy-Match-Match easy match
    3207   3.00  Hard     Easy     Match    Match    Hard-Easy-Match-Match match match
    3350   5.78  Hard     Easy     Hard     Hard     Hard-Easy-Hard-Hard   hard easy
    3350   5.78  Hard     Easy     Hard     Hard     Hard-Easy-Hard-Hard   easy hard
    3350   5.78  Hard     Easy     Hard     Hard     Hard-Easy-Hard-Hard   hard hard
    3961   10.00 Easy     Easy     Hard     Hard     Easy-Easy-Hard-Hard   easy easy
    3961   10.00 Easy     Easy     Hard     Hard     Easy-Easy-Hard-Hard   easy hard
    3961   10.00 Easy     Easy     Hard     Hard     Easy-Easy-Hard-Hard   hard hard
    

    第 3 步: 即使我想增加克的大小,这个解决方案也能满足我的要求。例如,对于3-gram,我可以简单地通过以下方式实现:

      df = as_tibble(df)
      df_test = df %>%
        unnest_tokens(trigram, all, token = "ngrams", n = 3)
    

    这将产生:

    userID Score Task_*A* Task_*B* Task_*C* Task_*D* all                   trigram
    3108  -8.00  Easy     Easy     Easy     Easy     Easy-Easy-Easy-Easy   easy easy easy
    3108  -8.00  Easy     Easy     Easy     Easy     Easy-Easy-Easy-Easy   easy easy easy
    3207   3.00  Hard     Easy     Match    Match    Hard-Easy-Match-Match hard easy match
    3207   3.00  Hard     Easy     Match    Match    Hard-Easy-Match-Match easy match match
    3350   5.78  Hard     Easy     Hard     Hard     Hard-Easy-Hard-Hard   hard easy hard
    3350   5.78  Hard     Easy     Hard     Hard     Hard-Easy-Hard-Hard   easy hard hard
    3961   10.00 Easy     Easy     Hard     Hard     Easy-Easy-Hard-Hard   easy easy hard
    3961   10.00 Easy     Easy     Hard     Hard     Easy-Easy-Hard-Hard   easy hard hard
    

    【讨论】:

      猜你喜欢
      • 2016-05-02
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 2016-04-07
      • 2018-08-10
      • 1970-01-01
      • 2014-09-08
      • 2011-01-20
      相关资源
      最近更新 更多