2015-03-30 4 views
-1

В моем кадре данных есть 10 столбцов и 100 000 строк, каждая строка является наблюдением, а столбцы - данными, относящимися к каждому наблюдению. Один из столбцов имеет дату наблюдения в юлийский день (т.е. feb 4 = день 34). Я хочу сократить свой набор данных, чтобы у меня были первые 10% наблюдений за PER-видами PER. Т.е., для видов 1 в 1901 году я хочу средний день появления на основе первых 10% наблюдений.R: выделение начальных 10%

Пример того, что у меня есть: note id = species, но как число. то есть синий = 1

date=c(3,84,98,100,34,76,86...) 
species=c(blue,purple,grey,purple,green,pink,pink,white...) 
id=c(1,2,3,2,4,5,5,6...) 
year=c(1901,2000,1901,1996,1901,2000,1986...) 
habitat=c(forest,plain,mountain...) 

ЭСТ Что я хочу: даты = с (3,84,76,86 ...) видовых = с (фиолетовым, розовым, розовым, белым ...) id = c (2,5,5,6 ...) год = c (1901,2000,2000,1986 ...)
habitat = c (лес, равнина, гора ...) новый = c (3,84,79,86 ...)

ответ

3

Предполагая, что набор данных dd определены ниже

set.seed(123) 
n <- 100000 
dd <- data.frame(year = sample(1901:2000, n, replace = TRUE), 
       date = sample(0:364, n, replace = TRUE), 
       species = sample(1:5, n, replace = TRUE)) 

1) base Совокупность dd с указанной функцией. не используются пакеты:

avg10 <- function(date) { 
    ok <- seq_along(date) <= length(date)/10 
    if (any(ok)) mean(date[ok]) else NA 
} 
aggregate(date ~ species + year, dd, avg10) 

2) data.table Вот data.table решение:

data.table(dd)[, 
    {ok <- .I <= .10 * .N; if (any(ok)) mean(date[ok]) else NA}, by = "species,year"] 

Примечание: Если вы не хотите NA-х затем использовать это вместо того, либо в случае утверждения выше, чтобы получить первую точку в этом случае:

if (any(ok)) mean(date[ok]) else date[1] 
+0

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

+0

Если количества строк слишком мало, их будет недостаточно, чтобы получить 10%, чтобы он возвращал NA.Это работает с данными, которые вы предоставили. –

+0

Не было бы лучше сначала сжать данные, поэтому есть только первые 10% наблюдений за каждый вид в год, а затем взять среднее значение этих дат за каждый год для каждого вида? – John

1

так же, как для вашего last question, dplyr может хорошо работать для вас:

Некоторые данные:

library(dplyr) 
set.seed(42) 
n <- 500 
dat <- data.frame(date = sample(365, size=n, replace=TRUE), 
        species = sample(5, size=n, replace=TRUE), 
        year = 1980 + sample(20, size=n, replace=TRUE)) 

Как это выглядит без фильтрации:

dat %>% group_by(year, species) %>% arrange(year, date) 
## Source: local data frame [500 x 3] 
## Groups: year, species 
## date species year 
## 1 50  1 1981 
## 2 138  1 1981 
## 3 174  1 1981 
## 4 179  1 1981 
## 5 200  1 1981 
## 6 332  1 1981 
## 7 31  2 1981 
## 8 52  2 1981 
## 9 196  2 1981 
## 10 226  2 1981 
## .. ...  ... ... 

Как это выглядит с первого на 10% по дате в течение каждого года:

dat %>% 
    group_by(year, species) %>% 
    filter(ntile(date, 10) == 1) %>% 
    arrange(year, date) 
## Source: local data frame [100 x 3] 
## Groups: year, species 
## date species year 
## 1 50  1 1981 
## 2 31  2 1981 
## 3 63  3 1981 
## 4 112  4 1981 
## 5  1  5 1981 
## 6 40  1 1982 
## 7 103  2 1982 
## 8 40  3 1982 
## 9 86  4 1982 
## 10 48  5 1982 
## .. ...  ... ... 

I ntile трюк делает то, что вы хотите: он разбивает данные в бункеры с одинаковым размером, поэтому он должен давать вам самые низкие 10% ваших дат.

EDIT

К сожалению, я пропустил mean там:

dat %>% group_by(year, species) %>% 
    filter(ntile(date, 10) == 1) %>% 
    summarise(date = mean(date)) %>% 
    arrange(year, date) 
## Source: local data frame [99 x 3] 
## Groups: year 
## year species date 
## 1 1981  5 1 
## 2 1981  2 31 
## 3 1981  1 50 
## 4 1981  3 63 
## 5 1981  4 112 
## 6 1982  1 40 
## 7 1982  3 40 
## 8 1982  5 48 
## 9 1982  4 86 
## 10 1982  2 103 
## .. ...  ... ... 
+0

Возможно ли вернуть значение для каждого наблюдения, которое будет означать средний день первых 10% на каждого вида в год, который полностью генерирует новую колонку? и просто исключить данные, которые не попадают в первые 10% наблюдений? – John

+0

Это замечательно! lat: как бы я устранил наблюдения из набора данных, которые выпадают за пределы начальных 10%? т.е. я хочу исключить строки, которые не использовались при вычислении средней даты. Огромное спасибо!! – John

+0

Это то, что делает часть 'filter()': разрешить только первые 10%. Вам нужно записать вывод в новую переменную с чем-то вроде 'datFiltered <- dat %>% group_by (год, вид)%>% ...'. – r2evans

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

  • Нет связанных вопросов^_^