Применить функцию к кадру данных на основе уникальных значений

Мне нужно применить функцию к кадру данных, подмноженому или сгруппированному по уникальным значениям.

Мои данные выглядят так:

FID FIX_NO ELK_ID ALTITUDE     XLOC    YLOC DATE_TIME JulDate
1   NA   5296    393 2260.785 547561.3 4771900        NA     140
2   NA   5297    393 2254.992 547555.9 4771906        NA     140
3   NA   5298    393 2256.078 547563.5 4771901        NA     140
4   NA   5299    393 2247.047 547564.7 4771907        NA     140
5   NA   5300    393 2264.875 547558.3 4771903        NA     140
6   NA   5301    393 2259.496 547554.1 4771925        NA     140
...
24247   NA   4389    527 2204.047 558465.7 4775358        NA     161
24248   NA   4390    527 2279.078 558884.1 4775713        NA     161
24249   NA   4391    527 2270.590 558807.9 4775825        NA     161
24250   NA   4392    527 2265.258 558732.2 4775805        NA     161
24251   NA   4393    527 2238.375 558672.4 4775781        NA     161
24252   NA   4394    527 2250.055 558686.6 4775775        NA     161

Моя цель — создать новый data.frame, случайным образом выбрав 4 строки для каждой JulDate для каждого уникального ELK_ID. Если я сделаю это вручную, для каждого уникального ELK_ID мой код будет следующим:

oneelk <- subset(dataset, ELK_ID == 393)
newdata <- do.call(rbind,lapply(split(oneelk,oneelk$JulDate), function(x)x[sample(1:nrow(x),4),]))

Есть >40 ELK_ID, поэтому мне нужно автоматизировать процесс. Пожалуйста, помогите!


person acb    schedule 11.12.2014    source источник
comment
Используйте кнопку {}, чтобы поместить данные в блоки кода.   -  person jlhoward    schedule 12.12.2014


Ответы (4)


Вот решение data.table.

library(data.table)
setDT(dataset)[,.SD[sample(.N,4)],by=list(ELK_ID,JulDate)]

#    ELK_ID JulDate FID FIX_NO ALTITUDE     XLOC    YLOC DATE_TIME
# 1:    393     140  NA   5297 2254.992 547555.9 4771906        NA
# 2:    393     140  NA   5299 2247.047 547564.7 4771907        NA
# 3:    393     140  NA   5298 2256.078 547563.5 4771901        NA
# 4:    393     140  NA   5300 2264.875 547558.3 4771903        NA
# 5:    527     161  NA   4394 2250.055 558686.6 4775775        NA
# 6:    527     161  NA   4392 2265.258 558732.2 4775805        NA
# 7:    527     161  NA   4390 2279.078 558884.1 4775713        NA
# 8:    527     161  NA   4393 2238.375 558672.4 4775781        NA

NB, это будет работать только в том случае, если для каждой комбинации ELK_ID и JulDate есть как минимум 4 строки.

person jlhoward    schedule 11.12.2014
comment
Спасибо за решение, к сожалению, похоже, что у меня есть некоторые ELK_ID с менее чем 4 JulDates. - person acb; 12.12.2014
comment
Затем используйте sample(.N,min(.N,4)) вместо sample(.N,4). Это потребует случайной выборки любого количества строк, до 4. - person jlhoward; 12.12.2014

Вы также можете создать индекс, используя tapply, а затем просто подмножество (при условии, что ваш набор данных называется df)

indx <- unlist(tapply(seq_len(dim(df)[1L]), 
                      df[, c("JulDate", "ELK_ID")], 
                      function(x) sample(x, 4)))
df[indx, ]
person David Arenburg    schedule 11.12.2014
comment
когда я определяю индекс, я получаю сообщение об ошибке, что «аргументы должны быть одинаковой длины». Я знаю, что для каждого значения ELK_ID есть соответствующее значение для JulDate, поэтому я не уверен, почему я получаю сообщение об ошибке. - person acb; 12.12.2014
comment
Причина, по которой вы получаете эту ошибку, заключается в том, что вы преобразовали свой набор данных в объект data.table (сначала вы запустили код @jihoward). Если вы хотите, чтобы это работало, запустите это на исходном наборе данных. - person David Arenburg; 14.12.2014

Попробуйте разделить, используя оба столбца, может быть split(dataset, dataset[, c("ELK_ID", "JulDate")])

person Chris S.    schedule 11.12.2014

Также можно добавить решение dplyr:

library(dplyr)
newdf <- yourdata %>%
          group_by(ELK_ID, JulDate) %>%
          sample_n(4)
person Nick DiQuattro    schedule 11.12.2014
comment
Я думаю, это именно то, что я хочу, но мне нужно одобрение администратора, чтобы обновить мою версию R, чтобы я мог получить доступ к dplyr. Дай знать, как дела! Спасибо! - person acb; 12.12.2014
comment
Решение с библиотекой (data.table) работало без обновления моей версии R. Спасибо за помощь! - person acb; 12.12.2014