Умножьте фрейм данных построчно - PullRequest
3 голосов
/ 04 сентября 2011

Входной файл:

df1 <- data.frame(row.names=c("w","x","y","z"), A=c(0,0,0,0), B=c(0,1,0,0), C=c(1,0,1,0), D=c(1,1,1,1))

  A B C D
w 0 0 1 1
x 0 1 0 1
y 0 0 1 1
z 0 0 0 1

Я хочу применить уравнение, т.е. умножить строку w на строку x, чтобы получить попарное значение для пары wx, следующим образом:

      A B C D
    w 0 0 1 1
X   x 0 1 0 1
--------------
   wx 0 0 0 1

дляполучить построчный анализ для wx, wy, wy, wz, xy, xz, yz.и сгенерируйте новый фрейм данных с 6 столбцами (два имени строки, за которыми следуют умноженные значения).

Это

w x 0 0 0 1
w y 0 0 1 1
w z 0 0 0 1
x y 0 0 0 1
x z 0 0 0 1
y z 0 0 0 1

Thanksssssss.

Ответы [ 4 ]

4 голосов
/ 04 сентября 2011
dat <- read.table(textConnection("  A B C D
+ w 0 0 1 1
+ x 0 1 0 1
+ y 0 0 1 1
+ z 0 0 0 1
+ "), header=TRUE)
> combos <- combn(rn,2)
> combos
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,] "w"  "w"  "w"  "x"  "x"  "y" 
[2,] "x"  "y"  "z"  "y"  "z"  "z" 

apply(combos,2, function(x) c(x[1], x[2], unlist(dat[x[1],]*dat[x[2],])))
  [,1] [,2] [,3] [,4] [,5] [,6]
  "w"  "w"  "w"  "x"  "x"  "y" 
  "x"  "y"  "z"  "y"  "z"  "z" 
A "0"  "0"  "0"  "0"  "0"  "0" 
B "0"  "0"  "0"  "0"  "0"  "0" 
C "0"  "1"  "0"  "0"  "0"  "0" 
D "1"  "1"  "1"  "1"  "1"  "1" 

Итак, окончательное решение:

t( apply(combos,2, function(x) c(x[1], x[2], unlist(dat[x[1],]*dat[x[2],]))) )

Если вы преобразуете комбо в кадр данных, вы также сможете использовать cbindmatrix как тип "числовой":

 cbind( as.data.frame(t(combos)), 
        t( apply(combos,2, function(x)  
                    unlist(dat[x[1],]*dat[x[2],]))) )

  V1 V2 A B C D
1  w  x 0 0 0 1
2  w  y 0 0 1 1
3  w  z 0 0 0 1
4  x  y 0 0 0 1
5  x  z 0 0 0 1
6  y  z 0 0 0 1
4 голосов
/ 04 сентября 2011

Если вам не нужны комбо-имена в результирующем объекте, тогда мы можем комбинировать элементы ответов @ DWin's и @ Owen, чтобы обеспечить действительно векторизованный подход к проблеме.(Вы можете добавить имена комбинаций в виде имен строк с одним дополнительным шагом в конце.)

Сначала данные:

dat <- read.table(con <- textConnection("  A B C D
w 0 0 1 1
x 0 1 0 1
y 0 0 1 1
z 0 0 0 1
"), header=TRUE)
close(con)

Возьмите идею combn() из ответа @ DWin, ноиспользуйте его для индексов строк из dat:

combs <- combn(seq_len(nrow(dat)), 2)

Строки combs теперь индексируют строки dat, которые мы хотим умножить вместе:

> combs
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    1    1    1    2    2    3
[2,]    2    3    4    3    4    4

Теперь мы возьмем идею, показанную @Owen, а именно dat[i, ] * dat[j, ], где i и j - первая и вторая строки combs соответственно.Мы конвертируем в матрицу с data.matrix(), так как это будет более эффективно для больших объектов, но код будет работать с dat также как фрейм данных.

mat <- data.matrix(dat)
mat[combs[1,], ] * mat[combs[2,], ]

, который производит:

> mat[combs[1,], ] * mat[combs[2,], ]
  A B C D
w 0 0 0 1
w 0 0 1 1
w 0 0 0 1
x 0 0 0 1
x 0 0 0 1
y 0 0 0 1

Чтобы увидеть, как это работает, обратите внимание, что mat[combs[k,], ] создает матрицу с различными строками, повторяемыми в порядке, указанном комбинациями:

> mat[combs[1,], ]
  A B C D
w 0 0 1 1
w 0 0 1 1
w 0 0 1 1
x 0 1 0 1
x 0 1 0 1
y 0 0 1 1
> mat[combs[2,], ]
  A B C D
x 0 1 0 1
y 0 0 1 1
z 0 0 0 1
y 0 0 1 1
z 0 0 0 1
z 0 0 0 1

Чтобы получить именно то, что опубликовал ОП, мы можемизменить имена строк с помощью второго combn() вызова:

> out <- mat[combs[1,], ] * mat[combs[2,], ]
> rownames(out) <- apply(combn(rownames(dat), 2), 2, paste, collapse = "")
> out
   A B C D
wx 0 0 0 1
wy 0 0 1 1
wz 0 0 0 1
xy 0 0 0 1
xz 0 0 0 1
yz 0 0 0 1
0 голосов
/ 29 мая 2015

Более короткий путь (я думаю), используя удивительный пакет plyr

Ваши данные. Рамка

df1 <- data.frame(row.names=c("w","x","y","z"), A=c(0,0,0,0), B=c(0,1,0,0), C=c(1,0,1,0), D=c(1,1,1,1))

YOUR_COMBS<-combn(rownames(df1),2)

А твой результат:)

require(plyr) #(version 1.81...in version 1.82 you can take the annoying 'X1' index out... )


     YOUR_RESULTS<-adply(YOUR_COMBS,2,function(x) {
      tmp_row<-data.frame(Comb=paste0(x,collapse = ''),df1[x[1],]*df1[x[2],])
 })
0 голосов
/ 04 сентября 2011

Если вы хотите умножить строки, я рекомендую преобразовать в матрицу:

> m = as.matrix(df1)

> m["x", ] * m["y", ]
A B C D 
0 0 0 1 

Конкретный результат, который вы хотите получить с помощью plyr,

library(plyr)

ldply(1:(nrow(m)-1), function(i)
    ldply((i+1):nrow(m), function(j) {
        a = row.names(m)[[i]]
        b = row.names(m)[[j]]

        do.call(data.frame,
            c(list(a=a, b=b), m[i,] * m[j,])
        )
    })
)

Извините частьэто выглядит немного волшебно - data.frames на самом деле не должны быть похожими на строки.Строки

do.call(data.frame,
    c(list(a=a, b=b), m[i,] * m[j,])
)

передаются в 6 столбцах: a и b для имен, соединенных (с c) в умноженную строку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...