применить () и вычислить долю первой строки для всех строк фрейма данных

#r #rows #apply #divide

#r #строки #применить #разделить

Вопрос:

У меня есть фрейм данных, как показано ниже, в котором указано количество травм по типу транспортного средства:

 trqldnum <- data.frame(motorveh=c(796,912,908,880,941,966,989,984),
                       motorcyc=c(257,295,326,313,403,389,474,496),
                       bicyc=c(109,127,125,137,172,146,173,178))
trqldnum

#  motorveh motorcyc bicyc
#1      796      257   109
#2      912      295   127
#3      908      326   125
#4      880      313   137
#5      941      403   172
#6      966      389   146
#7      989      474   173
#8      984      496   178
  

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

 trqldprop <- t(apply(trqldnum,1,function(x) {
                 x/c(trqldnum[1,1],trqldnum[1,2],trqldnum[1,3])
              }))
trqldprop

#  motorveh motorcyc    bicyc
#1 1.000000 1.000000 1.000000
#2 1.145729 1.147860 1.165138
#3 1.140704 1.268482 1.146789
#4 1.105528 1.217899 1.256881
#5 1.182161 1.568093 1.577982
#6 1.213568 1.513619 1.339450
#7 1.242462 1.844358 1.587156
#8 1.236181 1.929961 1.633028
  

Это кажется немного некрасивым, и мне нужно было бы вручную изменить знаменатель функции, если бы данные изменили форму. В итоге я получаю результат в виде списка списков, если я пытаюсь просто использовать следующее в инструкции apply().

 function(x) x/c(trqldnum[1,])
  

Я бы предпочел получить результат фрейма данных, как указано выше, но я просто запутался, пытаясь разобраться в этом.

Ответ №1:

Преобразуйте фрейм данных в матрицу и используйте матричные операции:

 m <- as.matrix(trqldnum)

trqldprop <- as.data.frame( t(t(m)/m[1,]) )

> trqldprop
  motorveh motorcyc    bicyc
1 1.000000 1.000000 1.000000
2 1.145729 1.147860 1.165138
3 1.140704 1.268482 1.146789
4 1.105528 1.217899 1.256881
5 1.182161 1.568093 1.577982
6 1.213568 1.513619 1.339450
7 1.242462 1.844358 1.587156
8 1.236181 1.929961 1.633028
  

Обратите внимание, что нам нужно транспонировать матрицу (см. t(m) ), потому что при делении матрицы на вектор операция выполняется по столбцам.

Комментарии:

1. Хороший ответ, если бы у меня было достаточно репутации, я бы 1 вам. Признаюсь, я не очень хорошо разбираюсь в матричных операциях, поэтому сегодня у меня есть тема для чтения.

Ответ №2:

Мне нравится plyr для этих задач, поскольку они позволяют вам указывать формат вывода. Вы можете превратить это в функцию, которая будет легко масштабироваться до большего количества столбцов и разных базовых уровней для разделения.

 FUN <- function(dat, baseRow = 1){
    require(plyr)   
    divisors <- dat[baseRow ,]
    adply(dat, 1, function(x) x / divisors)
}

FUN(trqldnum, 1)

  motorveh motorcyc    bicyc
1 1.000000 1.000000 1.000000
2 1.145729 1.147860 1.165138
3 1.140704 1.268482 1.146789
4 1.105528 1.217899 1.256881
5 1.182161 1.568093 1.577982
6 1.213568 1.513619 1.339450
7 1.242462 1.844358 1.587156
8 1.236181 1.929961 1.633028
  

Ответ №3:

Как насчет

 sweep(trqldnum,2,unlist(trqldnum[1,]),"/")
  

?

unlist Требуется для преобразования первой строки фрейма данных в вектор, который можно перемещать…

Ответ №4:

Некоторая версия решения Prasad без преобразования в матрицу.

 trqldnum/trqldnum[1,][rep(1,nrow(trqldnum)),]
  

Комментарии:

1. Повторив аналогичный анализ сегодня, я понимаю, что это можно было бы еще немного упростить, используя… trqldnum/trqldnum[rep(1,nrow(trqldnum)),]