Скажем, у меня есть следующий dataframe:Преобразование dataframe в расширенной матрицы в г
dfx <- data.frame(Var1=c("A", "B", "C", "D", "B", "C", "D", "C", "D", "D"),
Var2=c("E", "E", "E", "E", "A", "A", "A", "B", "B", "C"),
Var1out = c(1,-1,-1,-1,1,-1,-1,1,-1,-1),
Var2out= c(-1,1,1,1,-1,1,1,-1,1,1))
dfx
Var1 Var2 Var1out Var2out
1 A E 1 -1
2 B E -1 1
3 C E -1 1
4 D E -1 1
5 B A 1 -1
6 C A -1 1
7 D A -1 1
8 C B 1 -1
9 D B -1 1
10 D C -1 1
То, что вы видите здесь 10 строк, которые соответствуют Лицу между игроками A, B, C, D и E. Они играйте друг с другом один раз, а победитель каждого совпадения обозначается +1, а проигравший каждого совпадения обозначается -1 (помещается в соответствующий столбец Player Var1 приводит к Var1out, Player Var2 приводит к Var2out) ,
Желаемый результат.
Я хочу, чтобы преобразовать эту dataframe к этой матрице выходов (порядок строк не важны для меня, но, как вы можете видеть, каждая строка относится к уникальному матч-):
A B C D E
1 1 0 0 0 -1
2 0 -1 0 0 1
3 0 0 -1 0 1
4 0 0 0 -1 1
5 -1 1 0 0 0
6 1 0 -1 0 0
7 1 0 0 -1 0
8 0 -1 1 0 0
9 0 1 0 -1 0
10 0 0 1 -1 0
Что я сделал:
Мне удалось сделать эту матрицу обходным путем. Поскольку обходные пути имеют тенденцию быть медленными и менее удовлетворительными, мне было интересно, сможет ли кто-нибудь найти лучший способ.
Сначала я убедился, что в моих двух столбцах, содержащих игроков, есть уровни факторов, которые содержат все возможные игроки, которые когда-либо случаются (например, вы заметите, что игрок E никогда не встречается в Var1).
# Making sure Var1 and Var2 have same factor levels
levs <- unique(c(levels(dfx$Var1), levels(dfx$Var2))) #get all possible levels of factors
dfx$Var1 <- factor(dfx$Var1, levels=levs)
dfx$Var2 <- factor(dfx$Var2, levels=levs)
Затем я разделить dataframe на два - один для Var1 и Var1out, и один для Переменная2 и Var2out:
library(dplyr)
temp.Var1 <- dfx %>% select(Var1, Var1out)
temp.Var2 <- dfx %>% select(Var2, Var2out)
Здесь я использую model.matrix
расширить колонки от уровня фактора:
mat.Var1<-with(temp.Var1, data.frame(model.matrix(~Var1+0)))
mat.Var2<-with(temp.Var2, data.frame(model.matrix(~Var2+0)))
Затем я заменяю для каждой строки столбец «1», указывающий на наличие этого фактора, с правильным результатом и добавляем эти матрицы:
mat1 <- apply(mat.Var1, 2, function(x) ifelse(x==1, x<-temp.Var1$Var1out, x<-0) )
mat2 <- apply(mat.Var2, 2, function(x) ifelse(x==1, x<-temp.Var2$Var2out, x<-0) )
matX <- mat1+mat2
matX
Var1A Var1B Var1C Var1D Var1E
1 1 0 0 0 -1
2 0 -1 0 0 1
3 0 0 -1 0 1
4 0 0 0 -1 1
5 -1 1 0 0 0
6 1 0 -1 0 0
7 1 0 0 -1 0
8 0 -1 1 0 0
9 0 1 0 -1 0
10 0 0 1 -1 0
Хотя это работает, у меня есть ощущение, что, вероятно, я пропустил более простые решения этой проблемы. Благодарю.
После просмотра этот ответ я понял, что если OP не против переименования своих столбцов, они могут использовать 'merged.st ack' из моего пакета splitstackshape. См. [This Gist] (https://gist.github.com/mrdwab/98175d209b642ee39ae9) с таймингами. – A5C1D2H2I1M1N2O1R2T1
@ Ананда Махто Спасибо за тайминги. Я был немного удивлен, что «распространение» не так быстро. Возможно, 'dcast.data.table' станет лучшей альтернативой. – akrun
В настоящее время ~ 45% времени в вашей функции расходуется на шаг «unlist». Это резко падает *** *** с помощью 'use.names = FALSE' ... но все еще не имеет шанса против подхода к индексированию матрицы :-) – A5C1D2H2I1M1N2O1R2T1