2017-02-06 9 views
2

У меня есть кадр данных 400 строк и 1200 столбцов, а общая структура такова:Как пластинчатые столбцы в кадре данных и поместить результаты в одном кадре данных

> df=data.frame(Col1=paste0('row',1:15),metric1=sample(c('H','M','L'),15,replace = 1),metric2=sample(c('H','M'),15,replace = 1)) 
> df 
    Col1 metric1 metric2 ... 
1 row1  M  H 
2 row2  H  L 

Что бы как это сделать, - сравнить табличный результат каждой строки на основе подсчетов HML для каждого столбца.

Я попытался

> apply(df[,2:3],2,function(x) table(x)) 
$metric1 
x 
H L M 
1 7 7 

$metric2 
x 
H M 
10 5 

> 

Но результат список 1200, потому что не все колонки содержат все 3 значения, то есть один столбец имеет только HL, в то время как другой будет иметь HML.

Я также попытался агрегат, который приводит к ошибке

> apply(df[,2:3],2,function(x) aggregate(df$count,list(df[,x]),sum)) 
Error in `[.data.frame`(df, , x) : undefined columns selected 

но моя функция работает:

> aggregate(df$count,list(df[,2]),sum) 
    Group.1 x 
1  H 1 
2  L 7 
3  M 7 
> 

Я надеялся сохранить его в виде кадра данных, таких как:

> data.frame(var=c('H','M','L'),metric1=c(100,100,200),metric2=c(250,150,0)) 
    var metric1 metric2 
1 H  100  250 
2 M  100  150 
3 L  200  0 
> 
+0

У вас есть только эти 3 категории (H, L, M) или что-то более общее? – ira

ответ

2

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

apply(df[,2:3],2,function(x) table(factor(x,levels=c("H","M","L")))) 

    metric1 metric2 
H  6  11 
M  8  4 
L  1  0 
+2

Обратите внимание, что 'apply' использует цикл' for' под капотом и обычно медленнее, чем правильно реализованный цикл 'for'. – lmo

+0

Спасибо, lmo! Я этого не знал! Хотя, если другое решение после этого обращается после цикла for, будет ли оно еще быстрее (если предположительно sapply все еще работает цикл for под капотом)? Спасибо за понимание! :) – MPhD

+0

Канонический ответ в том, что это зависит. Вторая «проблема» с «apply» заключается в том, что она преобразует (копию) ее главный аргумент в матрицу до реализации поставленной функции. Здесь это включает преобразование из списка факторов в матрицу векторов символов, столбцы которых затем перерабатываются в факторы, по одному за раз. Это довольно дорогостоящий набор операций над большими наборами данных, которые может избежать цикл 'for'. Вы можете увидеть это преобразование в символ с помощью 'apply (df [, 2: 3], 2, function (x) x)'. – lmo

2

Я бы гарантировал, что все table приведут к 3 категориям, первыми преобразуя метрики в факторы ha ving H, L, M как уровни.

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

df=data.frame(Col1=paste0('row',1:15),metric1=sample(c('H','M','L'),15,replace = 1),metric2=sample(c('H','M'),15,replace = 1)) 
for (i in 2:ncol(df)){ 
    df[[i]] <- factor(df[[i]],levels=c("H","M","L")) 
} 

Затем по вызову применить таблицу на каждой колонны и стек:

sapply(df[-1],table) 
     metric1 metric2 
H  3  8 
M  1  7 
L  11  0 
0

В качестве альтернативы, вы можете сделать что-то вроде:

sumer <- function(data, pattern) 
{ 
     temp <- colSums(sapply(pattern, grepl, data)) 
     names(temp) <- pattern 
     temp 
} 


apply(df[, 2:3], 2, sumer, unique(df[, 2]))