Сравнение элемента со всеми другими элементами в той же переменной, используя for-loop в R - PullRequest
0 голосов
/ 19 сентября 2019

Я хочу создать матрицу данных, которая сравнивает детское производство токена слова с производством других токенов слова.Так, например, в следующем примере набора данных я хочу сравнить «tedi» в строке 1 с каждой другой формой в столбце Actual.

 library(tibble) 
  production.data <- tribble(~Subject, ~Age, ~Target, ~Actual,
       "subj1", "001126", "teddy", "tedi",
       "subj1", "001126", "teddy", "dedi",
       "subj1", "001126", "daddy", "dadi",
       "subj1", "001126", "daddy", "didi",
       "subj1", "001126", "daddy", "dati",
       "subj1", "001126", "baby", "beibi",
       "subj1", "001126", "Tigger", "tedi",
       "subj1", "001126", "doggy", "didi",
       "subj1", "001126", "milk", "mi")

В другом наборе данных, values ниже,У меня есть набор значений для каждого согласного / гласного в каждом слове.Я хочу сравнить каждое значение для слова 1 с каждым значением всех других слов в списке (обратите внимание, что фактический набор данных values на самом деле намного больше этого!).

 library(tibble) 
  values <- tribble(~Target, ~Actual, ~C1_Sonorant, ~C1_Consonantal,
       "teddy", "tedi", -1, 1,
       "teddy", "dedi", 1, 1,
       "daddy", "dadi", 1, 1, 
       "daddy", "didi", 1, 1,
       "daddy", "dati", 1, 1, 
       "baby", "beibi", -1, 1,
       "Tigger", "tedi", -1, 1,
       "doggy", "didi", 1, 1,
       "milk", "mi", 0, 0)

Мой вопрос: Как заставить R выполнять повторные вычисления (C1_Sonorant[1,]-C1_Sonorant[2,], C1_Consonantal[1,]-C1_Consonantal[2,]) по всем строкам в данных values?Я вполне уверен, что для этого потребуется цикл for, но я не уверен, как таким образом проводить сравнения между переменными.

Я думаю, что мне понадобятся разные матрицы для C1_Sonorant, C1_Consonantal,и т.д., и я ожидаю, что результат будет выглядеть примерно так:

 # C1_Sonorant

 output <- tribble(~Target, ~teddy, ~teddy, ~daddy, ~daddy,
       "teddy", 0, -2, -2, -2,
       "teddy", 2, 0, 0, 0,
       "daddy", 2, 0, 0, 0, 
       "daddy", 2, 0, 0, 0)

Ответы [ 2 ]

1 голос
/ 19 сентября 2019

Из того, что я понимаю, вы хотите сравнить каждую строку с каждой строкой, включая себя?

Вы можете сделать это с самостоятельным соединением (или перекрестным соединением) следующим образом.Но это, вероятно, не будет работать гладко с очень большим набором данных.

require(tidyverse)

df1 <- values %>% select(Target1 = Target,
                  Sonorant1 = C1_Sonorant,
                  Consonant1 = C1_Consonantal) %>%
  mutate(dummy = 1) %>%
  group_by(Target1) %>%
  mutate(newname1 = paste(Target1,row_number(),sep = "_")) %>%
  ungroup() %>%
  select(-Target1)

df2 <- df1 %>% select(newname2 = newname1,
                      Sonorant2 = Sonorant1,
                      Consonant2 = Consonant1,
                      dummy)

  df1 %>% inner_join(df2, by = 'dummy') %>%
    mutate(Son = Sonorant1 - Sonorant2,
           Con = Consonant1 - Consonant2) %>%
    select(newname1,newname2,Son,Con) %>%
    gather(key,value,-newname1,-newname2) %>%
    unite(column,newname2,key) %>%
    spread(column,value)

дает

# A tibble: 9 x 19
  newname1 baby_1_Con baby_1_Son daddy_1_Con daddy_1_Son daddy_2_Con daddy_2_Son daddy_3_Con daddy_3_Son doggy_1_Con
  <chr>         <dbl>      <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>
1 baby_1            0          0           0          -2           0          -2           0          -2           0
2 daddy_1           0          2           0           0           0           0           0           0           0
3 daddy_2           0          2           0           0           0           0           0           0           0
4 daddy_3           0          2           0           0           0           0           0           0           0
5 doggy_1           0          2           0           0           0           0           0           0           0
6 milk_1           -1          1          -1          -1          -1          -1          -1          -1          -1
7 teddy_1           0          0           0          -2           0          -2           0          -2           0
8 teddy_2           0          2           0           0           0           0           0           0           0
9 Tigger_1          0          0           0          -2           0          -2           0          -2           0
# ... with 9 more variables: doggy_1_Son <dbl>, milk_1_Con <dbl>, milk_1_Son <dbl>, teddy_1_Con <dbl>,
#   teddy_1_Son <dbl>, teddy_2_Con <dbl>, teddy_2_Son <dbl>, Tigger_1_Con <dbl>, Tigger_1_Son <dbl>

другой вариант может быть:

ones <- rep(1,nrow(values))
Son.mat <- values$C1_Sonorant %*% t(ones) - ones %*% t(values$C1_Sonorant)
rownames(Son.mat) <- values$Target
colnames(Son.mat) <- values$Target
Son.Mat

дает

       teddy teddy daddy daddy daddy baby Tigger doggy milk
teddy      0    -2    -2    -2    -2    0      0    -2   -1
teddy      2     0     0     0     0    2      2     0    1
daddy      2     0     0     0     0    2      2     0    1
daddy      2     0     0     0     0    2      2     0    1
daddy      2     0     0     0     0    2      2     0    1
baby       0    -2    -2    -2    -2    0      0    -2   -1
Tigger     0    -2    -2    -2    -2    0      0    -2   -1
doggy      2     0     0     0     0    2      2     0    1
milk       1    -1    -1    -1    -1    1      1    -1    0
0 голосов
/ 19 сентября 2019

У меня возникли небольшие проблемы с пониманием всего, что вы пытаетесь сделать, в частности, как ваш ожидаемый результат соотносится с двумя предыдущими задачами - например, каковы значения каждого из ваших ожидаемых значений, представленные в первых двух наборах данных?

Я мог бы предложить что-то для каждой из предыдущих задач в отдельности.Для первого есть метрика, называемая расстоянием Левенштейна, которая обеспечивает метрику «расстояния» между двумя словами, подробности см. ?adist.

Вы можете применить это к строкам первого набора данных согласно следующему:

apply(production.data, MARGIN = 1, FUN = function(r){
adist(r[["Target"]], r[["Actual"]])
})

Для второй задачи есть функция из пакета зоопарка для применения функции к скользящему окну наблюдений, которая называется rollapply, она может быть реализована примерно так:

zoo::rollapply(values, by.column = F,width = 2, FUN = function(x){
x <- as.data.frame(x)  %>% dplyr::mutate_at(dplyr::vars(dplyr::starts_with("C")), ~ as.numeric(.)) # Since the object is converted to a matrix and it coerces all values to character, convert it to a data.frame and change the numeric values with names starting with C back into numeric.
c(x[1,3, drop = T] - x[2,3, drop = T],# Subtract row 1 C1_sonorant from row 2
x[1,4, drop = T] - x[2,4, drop = T])# Subtract row 1 C1_Consonantal from row 2
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...