簡體   English   中英

R中行和列的值匯總

[英]Summary of values across rows and columns in R

我有一個看起來像這樣的數據集:

Group   A    B    C    D
XYZ     4    Na   1    3
XYZ     Na   2    2    1
DEF     4    3    2    1
DEF     3    3    1    1
PQR     1    Na   Na   1
PQR     3    2    2    4

我想要跨行和列的數據集摘要,以獲取每個值的計數,如下所示:

Group   4    3    2    1
XYZ     1    1    2    2
DEF     1    3    1    3
PQR     1    1    2    2

對於所有行和列,組XYZ的數據集中的計數為1,對於2和1為2,對於3為1.我可以通過創建4個新列4,3,2,1並獲取計數來完成此操作行方式然后列方式,但這不是有效和可擴展的。 我相信有更好的方法來完成這項工作。

使用reshape2包我們可以meltdcast如下,

library(reshape2)
dcast(na.omit(melt(df, id.vars = 'Group')), Group ~ value, fun.aggregate = length)
#  Group 1 2 3 4
#1   DEF 3 1 3 1
#2   PQR 2 2 1 1
#3   XYZ 2 2 1 1

這不使用包,只是一行。 這里DF$Group[row(DF[-1])]是一個Group標簽向量,這樣每個元素對應於unlist(DF[-1])數字向量unlist(DF[-1])

table(DF$Group[row(DF[-1])], unlist(DF[-1]))

贈送:

      1 2 3 4
  DEF 3 1 3 1
  PQR 2 2 1 1
  XYZ 2 2 1 1

如果問題中顯示的行和列的順序很重要,那么我們可以從兩個table參數中的每一個創建因子,並在所需的順序中定義因子級別。 在這種情況下,我們使用以下行代替上面的代碼行:

table(Group = factor(DF$Group[row(DF[-1])], unique(DF$Group)), factor(unlist(DF[-1]), 4:1))

贈送:

Group 4 3 2 1
  XYZ 1 1 2 2
  DEF 1 3 1 3
  PQR 1 1 2 2

上面產生了一個類"table"的對象。 對於列表頻率,這是一個特別合適的類。 例如,一旦處於這種形式, ftable可以用來輕松地重新排列它,如ftable(tab, row.vars = 2)ftable(tab, row.vars = 1:2) ,其中tab是上面的計算表。

如果首選data.frame,則將其轉換為:

cbind(Group = rownames(tab), as.data.frame.matrix(tab))

輸入data.frame DF在結尾的注釋2中可重復定義。

備擇方案

雖然以上似乎最直接的是其他一些替代方案也沒有使用包:

1)by對於具有相同Group值的每組行,匿名函數創建一個標識Group的data.frame,將除第一列以外的列轉換為具有指示級別和運行table的因子以獲取計數。 "by"返回的列表進行排序回原來的順序,我們rbind一切重新走到一起。

do.call("rbind",
   by(DF, DF$Group, function(x) {
      data.frame(Group = x[1,1], 
                 as.list(table(factor(unlist(x[, -1]), levels = 4:1))), 
                 check.names = FALSE)
   })[unique(DF$Group)])

贈送:

    Group 4 3 2 1
XYZ   XYZ 1 1 2 2
DEF   DEF 1 3 1 3
PQR   PQR 1 1 2 2

1a)這種略微縮短的變化也可行。 它返回一個使用行名標識組的矩陣。

kount <- function(x) table(factor(unlist(x), levels = 4:1))
m <- do.call("rbind", by(DF[, -1], DF$Group, kount)[unique(DF$Group)])

贈送:

> m
    4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2

2)外

gps <- unique(DF$Group)
levs <- 4:1
kount2 <- function(g, lv) sum(subset(DF, Group == g)[-1] == lv, na.rm = TRUE)
m <- outer(gps, levs, Vectorize(kount2))
dimnames(m) <- list(gps, levs))

給出這個矩陣:

> m
    4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2

3)sapply

kount3 <- function(g) table(factor(unlist(DF[DF$Group == g, -1]), levels = 4:1))
gps <- as.character(unique(DF$Group))
do.call("rbind", sapply(gps, kount3, simplify = FALSE))

贈送:

    4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2

4)聚合

aggregate(1:nrow(DF), DF["Group"],  function(ix) 
  table(factor(unlist(DF[ix, -1]), levels = 4:1)))[unique(DF$Group), ]

贈送:

  Group x.4 x.3 x.2 x.1
3   XYZ   1   1   2   2
1   DEF   1   3   1   3
2   PQR   1   1   2   2

5)tapply

do.call("rbind", tapply(1:nrow(DF), DF$Group, function(ix)
       table(factor(unlist(DF[ix, -1]), levels = 4:1))))[unique(DF$Group), ]

6)重塑

with(reshape(DF, dir = "long", varying = list(2:5)), 
  table(factor(Group, unique(DF$Group)), factor(A, 4:1)))

贈送:

    4 3 2 1
XYZ 1 1 2 2
DEF 1 3 1 3
PQR 1 1 2 2

注1: (1a),(2),(3),(5)和(6)產生一個矩陣或表結果,組為行名。 如果您更喜歡將Groups作為列的數據框,那么假設m是矩陣,請添加以下內容:

data.frame(Group = rownames(m), m, check.names = FALSE)

注2:可重復形式的輸入DF是:

Lines <- "Group   A    B    C    D
XYZ     4    Na   1    3
XYZ     Na   2    2    1
DEF     4    3    2    1
DEF     3    3    1    1
PQR     1    Na   Na   1
PQR     3    2    2    4"
DF <- read.table(text = Lines, header = TRUE, na.strings = "Na")

我們可以使用dplyr/tidyr

library(dplyr)
library(tidyr)
df1 %>% 
    mutate_each(funs(replace(., .=="Na", NA))) %>% 
    gather(Var, Val, A:D, na.rm=TRUE) %>%
    group_by(Group, Val) %>% 
    tally() %>%
    spread(Val, n)
#    Group   `1`   `2`   `3`   `4`
#* <chr> <int> <int> <int> <int>
#1   DEF     3     1     3     1
#2   PQR     2     2     1     1
#3   XYZ     2     2     1     1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM