R Перебрать data.frame и получить количество переменных [дубликаты]

У меня есть data.frame с двумя столбцами, уникальным идентификатором и результатом. Мне нужно пройти через data.frame и получить количество уникальных идентификаторов, а затем количество уникальных результатов. Столбец результатов может иметь три возможных результата: Положительный, Отрицательный или Неоднозначный. Так, например, если есть 10 идентификаторов «RVP PCR», мне нужно создать строку с еще четырьмя столбцами: «Количество», «Положительно», «Отрицательно», «Неоднозначно», и в этих столбцах должно быть количество раз. они произошли. Таким образом, в примере с 10 идентификаторами «RVP PCR» в выходной строке должен отображаться идентификатор, а не количество 10, 7 отрицательных, 1 положительный и 2 неоднозначных. Как бы вы сделали это с R ?

str(foo)
>
'data.frame':   51 obs. of  2 variables:
 $ identifier: Factor w/ 99 levels "ADENOPCR","ALB-BF",..: 51 51 56 56 57 57 57 57 18 18 ...
 $ result    : Factor w/ 3 levels "Ambiguous","Negative",..: 2 1 2 1 2 1 2 1 2 1 ...



dput(foo)
>
    structure(list(identifier = structure(c(80L, 80L, 80L, 80L, 80L, 
80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 
80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 80L, 64L, 
18L, 18L, 76L, 76L, 76L, 70L, 70L, 70L, 70L, 71L, 64L, 77L, 77L, 
77L, 77L, 77L, 77L, 77L, 77L, 76L), .Label = c("ADENOPCR", "ALB-BF", 
"ASPERAG", "ASPERAGB", "BDGLUCAN", "BLASTO", "BORD PCR", "BPERT", 
"CMV QNT", "CMVPCR", "COCCI", "COCCI G/M", "COCCI PAN", "COCCI-PPT", 
"CPNEUMOPCR", "CRP", "CRY BLD", "CWP-KOH", "DIFF CONF", "EBV PAN", 
"EBV PAN 2", "EBV QNT", "EXCEPT", "EXCEPT TT", "FLUFAC", "FUNG PKG", 
"FUNGSEQ", "GLU-FL", "HERP I", "HHV6PCR", "HISTO", "HISTO PPT", 
"HISTOAG S", "HISTOGM U", "HMPVFA", "HMPVPCR", "HSVPCR", "LEGAG-U", 
"LEGIONFA", "LEGIONPCR", "MA AFB", "MA FUNGAL", "MA MIC", "MA MTBPRIM", 
"MC AFB", "MC AFBID", "MC AFBR", "MC BAL", "MC BLD", "MC CYST", 
"MC FUNG", "MC FUNGID", "MC Legion", "MC LEGION", "MC MTD", "MC NOC", 
"MC RESP", "MC STAPH", "MC Strep", "MC STREP", "MC VRE", "MC W", 
"MICROSEQ", "MPNEUMOPCR", "MS CWP", "MTBRIF PCR", "MYCO-M", "NG REPORT", 
"ORGSEQ", "PARAFLUPCR", "PCP PCR", "PNEUMO AB", "PNEUMST", "PNEUMST R", 
"RESPMINI", "RESPMINI ", "RSPFA", "RSPFAC", "RSV", "RVP PCR", 
"RVPPCR", "SPN AG", "TP-FL", "V CMVC", "V FLUC", "V HSVC", "V HSVCT", 
"V RESPC", "V Urea", "V VIC", "V VIC R", "V VIRAL", "V VIRAL N", 
"V VIRAL R", "V VZV", "VDRL CSF", "VZVFAC", "VZVPCR", "WNILE PCR"
), class = "factor"), result = structure(c(2L, 2L, 3L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 2L, 2L, 2L, 2L, 3L, 
2L, 2L, 2L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("Ambiguous", 
"Negative", "Positive"), class = "factor")), .Names = c("identifier", 
"result"), row.names = 1500:1550, class = "data.frame")

person Nodedeveloper101    schedule 25.02.2016    source источник


Ответы (4)


library(dplyr)
library(tidyr)
foo %>%
  group_by(identifier, result) %>%
  summarise(n = n()) %>%
  spread(key = result, value = n, drop = FALSE, fill = 0) %>%
  mutate(Total = Ambiguous + Negative + Positive) %>%
  filter(Total > 0)

Результат

Source: local data frame [7 x 5]
Groups: identifier [7]

  identifier Ambiguous Negative Positive Total
      (fctr)     (dbl)    (dbl)    (dbl) (dbl)
1    CWP-KOH         0        2        0     2
2 MPNEUMOPCR         0        0        2     2
3 PARAFLUPCR         0        3        1     4
4    PCP PCR         0        0        1     1
5  RESPMINI          0        4        0     4
6      RSPFA         0        7        1     8
7    RVP PCR         0       28        2    30
person Thierry    schedule 25.02.2016
comment
Я вижу большой смысл в части fill = 0 для этого конкретного случая. Отсутствие счетчиков (0) концептуально отличается от отсутствия записей (NA). - person PavoDive; 25.02.2016
comment
Это именно то, что я искал, спасибо! @Тьерри - person Nodedeveloper101; 25.02.2016

Я не совсем уверен, каков ваш ожидаемый результат, но вы можете изменить свои данные:

library(reshape2)

dcast(foo, identifier~result, fun.aggregate= length)

Это производит:

  identifier Negative Positive
1    CWP-KOH        2        0
2 MPNEUMOPCR        0        2
3 PARAFLUPCR        3        1
4    PCP PCR        0        1
5  RESPMINI         4        0
6      RSPFA        7        1
7    RVP PCR       28        2

######## ИЗМЕНИТЬ, ЧТОБЫ ДОБАВИТЬ ##############

С данными, которые вы предоставили, "RVP PCR" никоим образом не даст заявленных вами результатов.

person PavoDive    schedule 25.02.2016

Данные в длинном формате. Сначала измените его на широкий, используя команду dcast из библиотеки reshape2. Добавьте столбец и возьмите сумму всех строк.

library(reshape2)    
widedata<-dcast(foo,identifier~result)
widedata$Count<-0 #adds column for Count
widedata$Count<-rowSums (widedata[,2:4], na.rm = FALSE, dims = 1) #[,2:4] since the data will have a column for ambiguous as well.
person Shreyas Joshi    schedule 25.02.2016

Без дополнительных пакетов можно сделать:

xtabs(~ identifier + result, data=droplevels(foo))

Это дает такой результат:

> xtabs(~ identifier + result, data=droplevels(foo))
            result
identifier   Negative Positive
  CWP-KOH           2        0
  MPNEUMOPCR        0        2
  PARAFLUPCR        3        1
  PCP PCR           0        1
  RESPMINI          4        0
  RSPFA             7        1
  RVP PCR          28        2

Если вам нужен кадр данных:

as.data.frame(unclass(xtabs(~ identifier + result, data=droplevels(foo))))

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

foo$count <- 1
aggregate(count ~ identifier+result, data=foo, FUN=length)
person jogo    schedule 25.02.2016
comment
Отличное базовое решение, но может ли результат быть фреймом данных? - person PavoDive; 25.02.2016
comment
@PavoDive Я отредактировал свой ответ, включив в него вариант фрейма данных. Если вам нравится мое базовое решение, вы можете проголосовать за него. - person jogo; 27.02.2016