R: группировка / разбиение набора данных по категориям в сочетании с apply.weekly () - PullRequest
2 голосов
/ 28 января 2012

Intro

Я еще не эксперт по R, поэтому прошу прощения за еще один вопрос, который мне, вероятно, следует смущать.В другой вопрос Я задал вопрос о стекопереработке и получил несколько очень полезных комментариев о том, как агрегировать нерегулярные ежедневные данные объекта xts в недельные значения с помощью функции apply.weekly().К сожалению, я не нашел такой функции, как tapply(), ddply(), by() или aggregate(), которая позволяет разделить по категориям, которая работает вместе с функцией apply.weekly().

Мои данные

Это мой пример набора данных.Я уже писал в другом вопросе.В целях иллюстрации я позволю себе также опубликовать его здесь:

example <- as.data.frame(structure(c(" 1", " 2", " 1", " 2", " 1", " 1", " 2", " 1", " 2", 
" 1", " 2", " 3", " 1", " 1", " 2", " 2", " 3", " 1", " 2", " 2", 
" 1", " 2", " 1", " 1", " 2", NA, " 2", NA, NA, " 1", " 3", " 1", 
" 3", " 3", " 2", " 3", " 3", " 3", " 2", " 2", " 2", " 3", " 3", 
" 3", " 2", " 2", " 3", " 3", " 3", " 3", " 1", " 2", " 1", " 2", 
" 2", " 1", " 2", " 1", " 2", " 2", " 2", " 3", " 1", " 1", " 2", 
" 2", " 3", " 3", " 2", " 2", " 1", " 2", " 1", " 1", " 2", NA, 
" 2", NA, NA, " 1", " 3", " 2", " 3", " 2", " 0", " 3", " 3", 
" 3", " 2", " 0", " 2", " 3", " 3", " 3", " 0", " 2", " 2", " 3", 
" 3", " 0", "12", " 5", " 9", "14", " 5", "tra", "tra", "man", 
"inf", "agc", "07-2011", "07-2011", "07-2011", "07-2011", "07-2011" 
), .indexCLASS = c("POSIXlt", "POSIXt"), .indexTZ = "", class = c("xts", 
"zoo"), .indexFORMAT = "%U-%Y", index = structure(c(1297642226, 
1297672737, 1297741204, 1297748893, 1297749513), tzone = "", tclass = c("POSIXlt", 
"POSIXt")), .Dim = c(5L, 23L), .Dimnames = list(NULL, c("rev_sit", 
"prof_sit", "emp_nr_sit", "inv_sit", "ord_home_sit", "ord_abr_sit", 
"emp_cost_sit", "usage_cost_sit", "tax_cost_sit", "gov_cost_sit", 
"rev_exp", "prof_exp", "emp_nr_exp", "inv_exp", "ord_home_exp", 
"ord_abr_exp", "emp_cost_exp", "usage_cost_exp", "tax_cost_exp", 
"gov_cost_exp", "land", "nace", "index"))))

Столбцы

"rev_sit", "prof_sit", "emp_nr_sit", "inv_sit",«ord_home_sit», «ord_abr_sit», «emp_cost_sit», «use_cost_sit», «tax_cost_sit», «gov_cost_sit», «rev_exp», «prof_exp», «emp_nr_exp», «inv_exp», «exc_exp», «ord_exp», «exp_hop», «ord_me»"," creation_cost_exp "," tax_cost_exp "," gov_cost_exp ",

относятся к вопросам в опросе.Было три варианта ответа: «1», «2» и «3».

Столбцы

"land", "nace"

- это категории с 16 и 8 уникальными коэффициентами соответственно.

Моя цель Моя цель - подсчитывать число «1», «2» и «3» по неделям.для каждой комбинации факторов категории в "NACE" и "Land".Моя идея состояла в том, чтобы заранее создать двоичные векторы для каждой возможности ответа {1,2,3} (example_1, example_2, example_2), а затем применить что-то вроде:

apply.weekly(example_1, function(d){ddply(d,list(example$nace,example$land),sum)})

Но это не работает ни с ddply, aggregate, by и т. Д.

Моя цель

Первоначально моей непрофессиональной работой было не создание временного ряда, а просто вектор даты example$date с указанным столбцом времени еженедельно через %V, а затем использовать, то есть:

tapply(example_1[,5], list(example$date,example$nace,example$land),sum)

, что я, конечно, должен был бы сделать для каждого из вышеупомянутых двадцати вопросов.Затем я получаю, например, например: _1:

неделя1, nace1.land1, nace1.land2, nace1.land3, ..., nace1.land16, nace2.land1, .., nace8.land16 week2, nace1.land1, nace1.land2, nace1.land3, ..., nace1.land16, nace2.land1, .., nace8.land16 ... ... weekn, nace1.land1, nace1.land2, nace1.land3, ..., nace1.land16, nace2.land1, .., nace8.land16

То же самое, что я должен сделать для 2 (example_2) и 3 (example_3), и это для каждого из 20 вопросов, чтобы получить все ввсе 16 * 8 * 3 * 20 = 7680 столбцов.Это экстремально, и, кроме того, при использовании этого метода продукт не является временным рядом, и поэтому он не упорядочен по неделям.

Резюме

Так что любой может научить меня или датьПодсказка, как использовать функцию apply.weekly() в сочетании с функциями, подобными tapply(), ddply(), by(), split(), unstack() и т. д., или любым другим способом для группировки, как описано выше.Каждый намек действительно ценится.Я так расстроен, что уже думаю о том, чтобы отказаться от эксперимента с R и вернуться к состоянию, в котором очень много вещей гораздо более интуитивно понятно с collapse() и by() и т. Д.поэтому, пожалуйста, помогите мне!

Ответы [ 2 ]

1 голос
/ 03 февраля 2012

большое спасибо за вашу помощь. Тем временем я был занят другими делами, но теперь я снова работал над своей проблемой, и с помощью ваших замечательных комментариев я нашел решение:

Я прекратил работать непосредственно с временными рядами, отложив этот шаг до конца моего анализа. Поэтому я беру вектор даты и преобразую его в недели:

библиотека (ISOweek) d $ index <- ISOweek (d $ date) </p>

(я делаю это с помощью ISOweek, поскольку я использую Windows)

тогда я использую комбинацию tapply и lapply. Следующая функция вычисляет количество положительных ответов в опросе (кодируется 1) для каждой календарной недели (d $ index = t [[22]]) и каждой комбинации двух категориальных столбцов t [[21]], t [ [22]]. На этом же этапе все превращается в фрейм данных:

groupweeksums <- function (x, t) {as.data.frame (tapply ((x == 1) * 1, list (t [[23]], t [[21]], t [[22 ]]), функция (d) sum (d, na.rm = TRUE)))} </p>

==> x обозначает конкретный столбец, t - фрейм данных (иначе я не знал, как это сделать, потому что в одном месте мне нужно обратиться к столбцу, а в другом - фрейме данных, и я хотел избежать много печатать); если d является фреймом данных, то:

df <- groupweeksums (d, d) </p>

чтобы мне не пришлось повторять эту процедуру для всех моих 20 вопросов, используйте lapply:

df <- as.data.frame (lapply (df [, 1:20], function (d) groupweeksums (d, euwifo)))) </p>

Это дает мне красивый фрейм данных со всем необходимым для дальнейшего анализа. Спасибо за вашу помощь, с вашими полезными комментариями я подошел ближе и ближе к решению !!!

P.S. Я также опубликую этот ответ на другой вопрос, который я разместил на stackoverflow, который был связан с этим. Я надеюсь, что это не проблема и не противоречит каким-либо правилам.

0 голосов
/ 28 января 2012

Я бы добавил столбец «недели», как вы предлагаете, но перед обработкой преобразуйте данные в высокий формат - вы можете преобразовать их обратно во временные ряды впоследствии, если это необходимо.

library(reshape2)
d <- melt(example, id.vars=c("land", "nace", "index"))
# You apparently want one of the followings
dcast( d, land + nace + index ~ value, length )
dcast( d, land + nace + index + variable ~ value, length )
dcast( d, land + nace + index ~ variable + value, length )

Эквивалентно, вы можете использовать ddply:

library(plyr)
d <- melt(example, id.vars=c("land", "nace", "index"))
ddply( d, 
  c("land", "nace", "index", "value"), 
  summarize, 
  number=length(value)  # The argument "value" does not play any role
)

Ваш столбец index содержит номер недели в текущем году (%Y-%U): это будет работать, только если все даты находятся в пределахтот же календарный год.Может быть безопаснее использовать фактическую дату вместо номера недели, например, воскресенье в начале текущей недели - это также упрощает преобразование результата во временные ряды.

week_start <- function(u) as.Date(u) - as.numeric(format(u, "%u"))
example$index <- weekstart( as.POSIXct(rownames(example)) )
# The following may also work.
example$index <- format( as.POSIXct(rownames(example)), "%G-%V" )
...