Количество факторов, встречающихся в группе в R

#r #dataframe

#r #фрейм данных

Вопрос:

Это мои данные:

 > head(Kandula_for_n)
                date      dist  date_only
1 2005-05-08 12:00:00  138.5861 2005-05-08
2 2005-05-08 16:00:00 1166.9265 2005-05-08
3 2005-05-08 20:00:00 1270.7149 2005-05-08
6 2005-05-09 08:00:00  233.1971 2005-05-09
7 2005-05-09 12:00:00 1899.9530 2005-05-09
8 2005-05-09 16:00:00  726.8363 2005-05-09
 

Теперь я хотел бы иметь дополнительный столбец с количеством (n) записей данных (dist) в день. Для 2005-05-08 это будет n = 3, так как есть 3 записи данных в 12, 16 и 20 часов. Я применил следующий код, который на самом деле дал мне то, что я хотел:

 ndist <-tapply(1:NROW(Kandula_for_n), Kandula_for_n$date_only, function(x) length(unique(x)))
 

После ndist<-as.data.frame(ndist) того , как я получил это:

 > head(ndist)
           ndist
2005-05-08     3
2005-05-09     4
2005-05-10     6
2005-05-11     4
2005-05-12     6
2005-05-13     6
 

Проблема в том, что счетчик находится вместе с date_only в одном столбце, который называется ndist. Но мне они понадобились бы в двух отдельных столбцах, один с count и один с date_only . Как это можно сделать?
Я думаю, это довольно просто, но я просто не понимаю.
Я был бы признателен, если бы вы могли высказать мне какие-либо соображения по этому поводу.

Спасибо за ваши усилия.

Ответ №1:

Просто потому tapply() , что мне трудно обернуть свой мозг, мне нравится использовать plyr для таких вещей:

 ## make up some data
## you get better/faster/more answers if you do this bit for us :)
dates <- seq(Sys.Date(), Sys.Date()   5, by = 1)
Kandula_for_n <- data.frame(date_only = sample( dates   5, 10, replace=TRUE ) , dist=rnorm(10) )

require(plyr)
ddply(Kandula_for_n, "date_only", function(x) data.frame(x, ndist=nrow(x)) )
 

Это даст вам что-то вроде:

     date_only       dist ndist
1  2011-10-30  0.2434168     5
2  2011-10-30 -0.9361780     5
3  2011-10-30  1.4593197     5
4  2011-10-30 -0.1851402     5
5  2011-10-30  0.6652419     5
6  2011-10-31  0.8876420     1
7  2011-11-03  0.5087175     2
8  2011-11-03 -1.0065152     2
9  2011-11-04  0.4236352     2
10 2011-11-04  0.4535686     2
 

строка ddply :

ddply(Kandula_for_n, "date_only", function(x) data.frame(x, ndist=nrow(x)) )

принимает входные данные, группирует их по date.only полю и для каждого уникального значения применяет анонимную функцию к фрейму данных, состоящему только из записей с одинаковым значением для date_only . Моя анонимная функция просто берет data.frame x и добавляет столбец с именем ndist , которое соответствует количеству строк в x нем.

Комментарии:

1. Спасибо вам за ваше предложение. Я уже несколько раз спотыкался о плир. Я думаю, что обязательно немного разберусь в этом. И с этого момента я обязательно постараюсь собрать эти данные…

Ответ №2:

Это всего лишь имена строк. Все готово:

 ndist$date = row.names(ndist)
 

РЕДАКТИРОВАТЬ: или ndist = data.frame(date = names(ndist), ndist) в зависимости от того, является ли это уже фреймом данных или нет.

Комментарии:

1. или data.frame(ndist,date_only=names(ndist),row.names=1:length(ndist))

2. или просто оставьте переменные идентификатора в качестве атрибутов имен (строк) и просто индексируйте напрямую, когда это необходимо. Это то, что я обычно делаю.

3. Спасибо, меня действительно смутили эти странные названия строк.

Ответ №3:

Как насчет чего-то более простого:

 as.data.frame(table(unique(Kandula_for_n)$date_only))
 

Комментарии:

1. это действительно очень просто. спасибо за это. Приятно знать этот фрагмент.