2015-02-18 4 views
2

Я ищу быстрое расширение следующего решения here. В нем Франк показывает, что для таблицы данных в следующем примереСоздание множества манекенов из существующего фрейма данных или таблицы данных

test <- data.table("index"=rep(letters[1:10],100),"var1"=rnorm(1000,0,1)) 

Вы можете быстро сделать манекены, используя следующий код

inds <- unique(test$index) ; test[,(inds):=lapply(inds,function(x)index==x)] 

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

new <- data.table("id" = rep(c("Jan","James","Dirk","Harry","Cindy","Leslie","John","Frank"),125), "index1"=rep(letters[1:5],200),"index2" = rep(letters[6:15],100),"index3" = rep(letters[16:19],250)) 

мне нужно сделать это для многих чайников и в идеале решение позволит мне получить 4 вещи:

  1. Общее кол-во каждого индекса
  2. Среднее время каждый индекс OCCURS
  3. Число индексов на один идентификатор
  4. Среднее значение каждого индекса на идентификатор

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

Благодаря

Simon

ответ

2

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

indcols <- paste0('index',1:3) 
lapply(new[,indcols,with=FALSE],table) # counts 
lapply(new[,indcols,with=FALSE],function(x)prop.table(table(x))) # means 

# or... 

lapply(
    new[,indcols,with=FALSE], 
    function(x){ 
    z<-table(x) 
    rbind(count=z,mean=prop.table(z)) 
    }) 

Это дает

$index1 
      a  b  c  d  e 
count 200.0 200.0 200.0 200.0 200.0 
mean 0.2 0.2 0.2 0.2 0.2 

$index2 
      f  g  h  i  j  k  l  m  n  o 
count 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 100.0 
mean 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 

$index3 
      p  q  r  s 
count 250.00 250.00 250.00 250.00 
mean 0.25 0.25 0.25 0.25 


Предыдущий подход будет работать на data.frame или data.table, но довольно сложный. С data.table, можно использовать melt синтаксис:

melt(new, id="id")[,.(
    N=.N, 
    mean=.N/nrow(new) 
), by=.(variable,value)] 

, который дает

variable value N mean 
1: index1  a 200 0.20 
2: index1  b 200 0.20 
3: index1  c 200 0.20 
4: index1  d 200 0.20 
5: index1  e 200 0.20 
6: index2  f 100 0.10 
7: index2  g 100 0.10 
8: index2  h 100 0.10 
9: index2  i 100 0.10 
10: index2  j 100 0.10 
11: index2  k 100 0.10 
12: index2  l 100 0.10 
13: index2  m 100 0.10 
14: index2  n 100 0.10 
15: index2  o 100 0.10 
16: index3  p 250 0.25 
17: index3  q 250 0.25 
18: index3  r 250 0.25 
19: index3  s 250 0.25 

Этот подход был упомянут @Arun в комментарии (и осуществляется его также, я думаю .. ?). Чтобы увидеть, как это работает, сначала взгляните на melt(new, id="id"), который преобразует исходную таблицу данных.

Как указано в комментариях, для плавления таблицы данных необходимо установить и загрузить reshape2 для некоторых версий пакета data.table.



Если вы нужны манекены, они могут быть выполнены в виде петли, как в связанном вопрос:

newcols <- list() 
for (i in indcols){ 
    vals = unique(new[[i]]) 
    newcols[[i]] = paste(vals,i,sep='_') 
    new[,(newcols[[i]]):=lapply(vals,function(x)get(i)==x)] 
} 

Это хранит группы столбцов, связанных с каждой переменной в newcols для удобство.Если вы хотите, чтобы сделать табуляцию только с этими манекенами (вместо основных переменных, как в растворе выше), вы могли бы сделать

lapply(
    indcols, 
    function(i) new[,lapply(.SD,function(x){ 
    z <- sum(x) 
    list(z,z/.N) 
    }),.SDcols=newcols[[i]] ]) 

, который дает аналогичный результат. Я просто написал это так, чтобы проиллюстрировать, как можно использовать синтаксис data.table. Можно снова избежать квадратные скобки и .SD здесь:

lapply(
    indcols, 
    function(i) sapply(
    new[, newcols[[i]], with=FALSE], 
    function(x){ 
     z<-sum(x) 
     rbind(z,z/length(x)) 
    })) 

Но в любом случае: просто использовать table, если вы можете держать на основных переменных.

+0

Не было бы легче, если бы мы * расплавились * это? то есть для первых двух частей «расплавить (новый, id =« id ») [,. (N = .N, mean = .N/nrow (new)), by =. (variable, value)]'. Добавьте 'id' к переменной группировки для последних 2 ..? – Arun

+0

@ Арун: Возможно. Я еще не знаком с синтаксисом «расплав». Я бы попробовал, но 'melt' и' melt.data.table' говорят: «Не удалось найти функцию» (даже если 'help (melt.data.table)' работает). Я предполагаю, что моя установка пакета не обновлено для этого еще ...? В любом случае, я думаю, вы бы лучше позиционировались, чтобы ответить с этим синтаксисом. Не стесняйтесь редактировать или добавлять другой ответ. Мне интересно посмотреть, как это работает. – Frank

+1

Версии <1.9.4 требует ' reshape2' для загрузки, вам это не нужно от '1.9.5 +'. – Arun

Смежные вопросы