Как создать матрицу совместного появления, рассчитанную по комбинациям по идентификатору / строке в R? - PullRequest
2 голосов
/ 09 января 2020

Обновление

Спасибо @jazzurro за его ответ. Это заставило меня понять, что дубликаты могут только усложнить вещи. Я надеюсь, что сохранение только уникальных значений / строк упрощает задачу. *

df <- data.frame(ID = c(1,2,3,4,5), 
                  CTR1 = c("England", "England", "England", "China", "Sweden"),
                  CTR2 = c("England", "China", "China", "England", NA),
                  CTR3 = c("USA", "USA", "USA", "USA", NA),
                  CTR4 = c(NA, NA, NA, NA, NA),
                  CTR5 = c(NA, NA, NA, NA, NA),
                  CTR6 = c(NA, NA, NA, NA, NA))


ID CTR1    CTR2    CTR3 CTR4 CTR5 CTR6
1  England China   USA
2  England China   USA
3  England China   USA
4  China   England USA
5  Sweden

Цель по-прежнему заключается в создании матрицы совместного использования (сейчас) на основе следующих четырех условий:

  1. Отдельные наблюдения без дополнительных наблюдений по идентификатору / строке не учитываются, т. Е. Строка, в которой один раз указана только одна страна, считается как 0.

  2. Комбинация / ко - вхождение должно быть подсчитано как 1.

  3. При нахождении в комбинации также учитывается как самосочетание (США-США), т. е. присваивается значение 1.

  4. Нет значения более 1, назначенного комбинации по строке / идентификатору.

Ожидаемый результат

         China   England   USA   Sweden

China    4        4         4      0

England  4        4         4      0        

USA      4        4         4      0

Sweden   0        0         0      0

* Я использовал код из здесь , чтобы удалить все неуникальные наблюдения.


Исходное сообщение

Предположим, у меня есть набор данных с небольшим числом столбцов di git (немного NA / пусто) и более 100 000 строк, представленных в следующем примере кадра данных

df <- data.frame(ID = c(1,2,3,4,5), 
                  CTR1 = c("England", "England", "England", "China", "England"),
                  CTR2 = c("England", "China", "China", "England", NA),
                  CTR3 = c("England", "China", "China", "England", NA),
                  CTR4 = c("China", "USA", "USA", "China", NA),
                  CTR5 = c("USA", "England", "USA", "USA", NA),
                  CTR6 = c("England", "China", "USA", "England", NA))


df

ID   CTR1    CTR2    CTR3    CTR4   CTR5    CTR6         
1    England England England China  USA     England 
2    England China   China   USA    England China
3    England China   China   USA    USA     USA  
4    China   England England China  USA     England
5    England 

и я хочу сосчитать совпадения по идентификатору / строке, чтобы получить матрицу совпадений, которая суммирует совпадение по идентификатору / строке только один раз, что означает, что никакое значение больше 1 не будет назначить комбинации (т. е. присвоить значение 1 для существования совместного вхождения, независимого от частот и порядка в ряду, присвоить значение 0 для отсутствия одновременного вхождения / комбинации по идентификатору / строке),

1 England-England-England => 1
2 England-England => 1
3 England-China => 1
4 England- => 0

Еще один важный аспект касается подсчета наблюдений, которые появляются один раз подряд, но в сочетании с другими, например, США в строке 1 . Они должны получить значение 1 для своего совместного вхождения (так как они находятся в комбинации, хотя и не с самими собой), чтобы комбинации США-США также получили назначенное значение 1.

1    England England England China  USA  England 
USA-USA => 1
China-China => 1
USA-China => 1
England-England => 1
England-USA => 1
England-China => 1

Из-за того, что количество строк не должно> 1 для комбинации по строке / идентификатору, это приводит к:

        China   England   USA 

China    1        1         1        

England  1        1         1        

USA      1        1         1

Это должно привести к следующему результату на основе примера кадра данных, где Значение 4 присваивается каждой комбинации на основе того факта, что каждая комбинация произошла как минимум в четырех строках, и каждая строка является частью комбинации исходного кадра данных:

         China   England   USA 

China    4        4         4        

England  4        4         4        

USA      4        4         4

Таким образом, существует пять условий для подсчет:

  1. Отдельные наблюдения без дополнительных наблюдений по идентификатору / строке не учитываются, т. е. строка с одной единственной страной не учитывается.
  2. Комбинация должна учитываться как 1 .
  3. Наблюдения, происходящие более одного раза, не способствуют более высокой ценности взаимодействия, то есть нескольким случаям одного и того же взаимодействия. Untry не имеет значения.
  4. Нахождение в комбинации (даже в том случае, если одна и та же страна не появляется дважды подряд) приводит к тому, что считается как самосочетание, т.е. присваивается значение 1.
  5. Не существует значения более 1, назначенного комбинации по строке / идентификатору.

Я пытался реализовать это с помощью dplyr, data.table, base aggregate или plyr корректирующий код от [1] , [2] , [3] , [4] , [5 ] и [6] но так как мне не важен порядок в ряду, но я также не хочу суммировать все комбинации в ряду, у меня нет ожидаемого результата пока.

Я новичок в R. Любая помощь очень ценится.

Ответы [ 2 ]

2 голосов
/ 09 января 2020

ДАННЫЕ

Я изменил ваши данные, чтобы данные могли отражать вашу реальную ситуацию.

#   ID    CTR1    CTR2    CTR3  CTR4    CTR5    CTR6
#1:  1 England England England China     USA England
#2:  2 England   China   China   USA England   China
#3:  3 England   China   China   USA     USA     USA
#4:  4   China England England China     USA England
#5:  5  Sweden    <NA>    <NA>  <NA>            <NA>


df <- structure(list(ID = c(1, 2, 3, 4, 5), CTR1 = c("England", "England", 
"England", "China", "Sweden"), CTR2 = c("England", "China", "China", 
"England", NA), CTR3 = c("England", "China", "China", "England", 
NA), CTR4 = c("China", "USA", "USA", "China", NA), CTR5 = c("USA", 
"England", "USA", "USA", ""), CTR6 = c("England", "China", "USA", 
"England", NA)), class = c("data.table", "data.frame"), row.names = c(NA, 
-5L))

ОБНОВЛЕНИЕ

После просмотра предыдущего вопроса ОП у меня появилась ясная картина. Я думаю, это то, что ты хочешь, Себ.

# Transform the data to long-format data. Remove rows that have zero character (i.e, "") or NA. 

melt(setDT(df), id.vars = "ID", measure = patterns("^CTR"))[nchar(value) > 0 & complete.cases(value)] -> foo

# Get distinct value (country) in each ID group (each row)
unique(foo, by = c("ID", "value")) -> foo2

# https://stackoverflow.com/questions/13281303/creating-co-occurrence-matrix
# Seeing this question, you want to create a matrix with crossprod().

crossprod(table(foo2[, c(1,3)])) -> mymat

# Finally, you need to change diagonal values. If a value is equal to one,
# change it to zero. Otherwise, keep the original value.

diag(mymat) <- ifelse(diag(mymat) <= 1, 0, mymat)

#value
#value     China England Sweden USA
#China       4       4      0   4
#England     4       4      0   4
#Sweden      0       0      0   0
#USA         4       4      0   4
1 голос
/ 10 января 2020

Вот вариант с использованием base::table:

#get paired combi and remove those from same country
pairsDF <- as.data.frame(do.call(rbind, 
    by(df, df$ID, function(x) t(combn(unlist(x[-1L]), 2L)))))

#tabulate pairs
duppairs <- rbind(pairsDF, data.frame(V1=pairsDF$V2, V2=pairsDF$V1))
tab <- table(duppairs, useNA="no")

#set diagonals to be the count of countries if count is at least 2
cnt <- c(table(unlist(df[-1L])))
cnt[cnt==1L] <- 0L
diag(tab) <- cnt[names(diag(tab))]

вывод:

         V2
V1        China England Sweden USA
  China       4       4      0   4
  England     4       4      0   4
  Sweden      0       0      0   0
  USA         4       4      0   4

данные:

df <- data.frame(ID = c(1,2,3,4,5), 
    CTR1 = c("England", "England", "England", "China", "Sweden"),
    CTR2 = c("China", "China", "China", "England", NA),
    CTR3 = c("USA", "USA", "USA", "USA", NA),
    CTR4 = c(NA, NA, NA, NA, NA),
    CTR5 = c(NA, NA, NA, NA, NA),
    CTR6 = c(NA, NA, NA, NA, NA))
...