R как извлечь n-граммовые строки - PullRequest
1 голос
/ 01 ноября 2019

У меня есть фрейм данных 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_alpha, Task_beta, Task_Charlie, Task_Delta) и показателями.

Моя гипотеза состоит в том, что последовательность 2-gram или bi-gram 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

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Во-первых, вам нужно преобразовать все ваши факторы в символы (в противном случае на следующем шаге вместо использования значений ваших факторов 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
0 голосов
/ 04 ноября 2019

Мне удалось решить эту проблему, как показано ниже:

Шаг 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
...