2016-12-23 2 views
2

У меня есть следующие dataframe, df:г: группа по нескольким столбцам и сосчитать

LeftOrRight SpeedCategory NumThruLanes 
R   25to45   3    
L   45to62   2   
R   Gt62   1   

Я хочу сгруппировать его по SpeedCategory и проходным других столбцов, чтобы получить частоту каждого уникального кода в каждой скорости категорию-- что-то вроде этого:

    25to45 45to62 Gt62 
LeftOrRight L  0  1 0 
       R  1  0 1 
NumThruLanes 1  0  0 1 
       2  0  1 0 
       3  1  0 0 

ближайший я смог прийти к это:

for (col in df){ 
tbl <- table(col, df$SpeedCategory) 
print(tbl) 
} 

, которая печатает следующий (первый SpeedCategory, затем NumThruLanes):

col 25to45 45to62 Gt62 
    L  0  1 0 
    R  1  0 1 

col 25to45 45to62 Gt62 
    1  0  0 1 
    2  0  1 0 
    3  1  0 0 

Я уверен, что я могу достичь своей цели с aggregate() или, может быть group_by от dplyr, но я новичок в R и не могу понять из синтаксиса. В pandas я бы использовал MultiIndex, но я не знаю, что такое эквивалент R, так что Google трудно.

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

ответ

4

Пакета tables позволяет легко таблицам формата в очень специфических способах. Синтаксис требует некоторого привыкания, но для этой проблемы довольно прямолинейно:

exd <- read.table(text = "LeftOrRight SpeedCategory NumThruLanes 
R   25to45   3    
L   45to62   2   
R   Gt62   1", header = TRUE)  

## to get counts by default we need everything to be categorical 
exd$SpeedCategory <- factor(exd$SpeedCategory) 

library(tables) 
tabular(LeftOrRight + NumThruLanes ~ SpeedCategory, data = exd) 

##    SpeedCategory    
##    25to45  45to62 Gt62 
## LeftOrRight L 0    1  0 
##    R 1    0  1 
## NumThruLanes 1 0    0  1 
##    2 0    1  0 
##    3 1    0  0 

Если у вас есть много столбцов перебрать, можно построить формулу программно, например,

tabular(as.formula(paste(paste(names(exd)[-2], collapse = " + "), 
         names(exd)[2], sep = " ~ ")), 
     data = exd) 

В качестве бонуса используются методы html и latex, что позволяет легко помечать ваш стол для включения в статью или отчет.

+1

Это именно то, что мне нужно, спасибо! Мне пришлось преобразовать все мои столбцы в факторы с помощью lapply (df, factor), и после этого он отлично справился. – ale19

0

Это не будет делать все за один проход, но может заставить вас идти в правильном направлении

library(reshape2) 

dcast(df, LeftOrRight ~ SpeedCategory, fun.aggregate = length) 
dcast(df, NumThruLanes ~ SpeedCategory, fun.aggregate = length) 
0

С dcast из reshape2 пакета, который вы могли бы сделать:

library("reshape2") 

DF=read.table(text="LeftOrRight SpeedCategory NumThruLanes 
R   25to45   3    
L   45to62   2   
R   Gt62   1",header=TRUE,stringsAsFactors=FALSE) 

LR_Stat = dcast(DF,LeftOrRight ~ SpeedCategory,length,fill=0) 
LR_Stat 
# LeftOrRight 25to45 45to62 Gt62 
#1   L  0  1 0 
#2   R  1  0 1 

Lanes_Stat = dcast(DF,NumThruLanes ~ SpeedCategory,length,fill=0) 
Lanes_Stat 
# NumThruLanes 25to45 45to62 Gt62 
#1   1  0  0 1 
#2   2  0  1 0 
#3   3  1  0 0 

Обратите внимание, что LR_Stat должен имеют 1 для диапазона 45to62 в вашем ожидаемом выходе

+0

Исправлено, спасибо! Это работает, но у меня много столбцов, чтобы пройти. Есть ли способ сделать это без явного обозначения столбцов?Я пробовал зацикливание и добавление каждого объекта в пустой фреймворк, но это, похоже, не работает ... – ale19

3

Вы можете сделать все за один проход, используя lapply() вместо цикла for:

tab_list <- lapply(df[, -2], function(col) table(col, df$SpeedCategory)) 
tab_list 
## $LeftOrRight 
##  
## col 25to45 45to62 Gt62 
## L  0  1 0 
## R  1  0 1 
## 
## $NumThruLanes 
##  
## col 25to45 45to62 Gt62 
## 1  0  0 1 
## 2  0  1 0 
## 3  1  0 0 

Вы можете объединить таблицы в одну, используя rbind() с do.call():

do.call(rbind, tab_list) 
## 25to45 45to62 Gt62 
## L  0  1 0 
## R  1  0 1 
## 1  0  0 1 
## 2  0  1 0 
## 3  1  0 0 

можно получить столбец в таблице вывода, которая указывает имя столбца из исходного кадра данных. Для достижения этой цели необходимо lapply() над именами столбцов с несколько более сложной функцией:

tab_list <- lapply(names(df)[-2], function(col) { 
    tab <- table(df[, col], df[, "SpeedCategory"]) 
    name_col <- c(col, rep("", nrow(tab) - 1)) 
    mat <- cbind(name_col, rownames(tab), tab) 
    as.data.frame(mat) 
    }) 
do.call(rbind, tab_list) 
##  name_col V2 25to45 45to62 Gt62 
## L LeftOrRight L  0  1 0 
## R    R  1  0 1 
## 1 NumThruLanes 1  0  0 1 
## 2    2  0  1 0 
## 3    3  1  0 0 
+0

Это выглядит многообещающим. Есть ли способ сохранить имена столбцов для каждого разбиения строк (LeftOrRight, NumThruLanes и т. Д.) В do.call() (кроме ручного добавления столбца), чтобы он выглядел немного больше, чем мой желаемый результат? – ale19