2016-03-22 2 views
4

H, У меня есть кадр данных, как это:обобщать группы в интервалы с использованием dplyr

d <- data.frame(v1=seq(0,9.9,0.1), 
      v2=rnorm(100), 
      v3=rnorm(100)) 

> head(d) 
    v1   v2   v3 
1 0.0 -0.01431916 -0.5005415 
2 0.1 -1.01575590 1.5307473 
3 0.2 1.00081065 -0.1730830 
4 0.3 -1.20697918 0.5105118 
5 0.4 -2.16698578 -1.0120544 
6 0.5 0.33886508 0.4797016 

теперь я хочу новый кадр данных, который суммирует все значения в интервалах 0-0.99, 1-1.99, 2 -2,99, 3-3.99, .... в среднем, например

как это

start end mean.v2 mean.v3 
    0 1  0.2  0.1 
    1 2  0.5  0.4 

и так далее

благодаря

Update Я хотел бы добавить, что в моих реальных данных устанавливающих наблюдений в каждом интервале имеют разную длину, и они не всегда начинаются с нуля или в конце в 10

+0

Вы можете использовать 'cut'. Возможно, 'd%>% group_by (v1 = cut (v1, breaks = c (-Inf, 0, 0.99, 1.99, 2.99, Inf)))%>% summaryise_each (funs (mean))' – akrun

+0

@akrun Я добавил некоторые дополнительную информацию на этот вопрос. Должен быть способ, когда мне не нужно устанавливать интервалы вручную – spore234

+0

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

ответ

4

здесь является одним из способов использования cut() как это было предложено @akrun: ответ

d %>% mutate(ints = cut(v1 ,breaks = 11)) %>% 
    group_by(ints) %>% 
    summarise(mean.v2 = mean(v2) , mean.v3 = mean(v3)) 
+0

спасибо, но я добавил некоторые дополнительные ограничения, которые я забыл. Наблюдения в каждом интервале могут быть разными, и они должны работать в разных наборах данных с разными начальными и конечными значениями. – spore234

+0

Мое решение не зависит от количества наблюдений в каждом интервале и их диапазоне, вы просто устанавливаете количество требуемых разрывов. Возможно, я неправильно понимаю вас; в этом случае вам следует предоставить минимальный объем и ожидаемый результат. –

+0

поэтому перерывы - это что-то вроде max (потолок (d $ v1)) + 1? Есть ли способ получить скобки включения интервалов от (..] до [..)? – spore234

2

на основе @David H "s, с 2-х вариантов на выбор:

  1. Сформировать интервалы с cut() использованием вектора разрывов
  2. Сформировать интервалы с floor() вместо cut()

Создание данных

set.seed(33) 
d <- data.frame(v1=seq(0,9.9,0.1), 
      v2=rnorm(100), 
      v3=rnorm(100)) 

Сформировать интервалы с cut() использованием вектора обрывов

Для этого простой пример, вы могли бы использовать breaks <- 0:10, но чтобы быть более общим, давайте возьмем min и max d$v1.

breaks <- floor(min(d$v1)):ceiling(max(d$v1)) 
breaks 
# [1] 0 1 2 3 4 5 6 7 8 9 10 

Обобщить через интервалы 0-0.99, 1-1.99, 2-2.99, 3-3.99, ....

d %>% 
    mutate(interval = cut(v1, 
          breaks, 
          include.lowest = TRUE, 
          right = FALSE)) %>% 
    group_by(interval) %>% 
    summarise(mean.v2 = mean(v2) , mean.v3 = mean(v3)) 

# Source: local data frame [10 x 3] 
# 
# interval  mean.v2  mean.v3 
#  (fctr)  (dbl)  (dbl) 
# 1  [0,1) -0.13040624 -0.20781247 
# 2  [1,2) 0.26505794 0.51990167 
# 3  [2,3) 0.13451628 1.12066174 
# 4  [3,4) 0.23451272 -0.14773437 
# 5  [4,5) 0.34326922 0.28567969 
# 6  [5,6) -0.77059944 -0.16629580 
# 7  [6,7) -0.17617190 0.03320797 
# 8  [7,8) 0.86550135 -0.24664350 
# 9  [8,9) -0.06652047 -0.27798769 
# 10 [9,10] -0.10424865 0.24060163 

Генерировать интервалы с floor() вместо cut()

жульничать немного, вычитая крошечное число 1e-9 с конца каждого интервала.

d %>% 
    mutate(start = floor(v1), end = start + 1 - 1e-9) %>% 
    group_by(start, end) %>% 
    summarise_each(funs(mean)) 

# Source: local data frame [10 x 4] 
# Groups: start [?] 
# 
# start end  mean.v2  mean.v3 
# (dbl) (dbl)  (dbl)  (dbl) 
# 1  0  1 -0.13040624 -0.20781247 
# 2  1  2 0.26505794 0.51990167 
# 3  2  3 0.13451628 1.12066174 
# 4  3  4 0.23451272 -0.14773437 
# 5  4  5 0.34326922 0.28567969 
# 6  5  6 -0.77059944 -0.16629580 
# 7  6  7 -0.17617190 0.03320797 
# 8  7  8 0.86550135 -0.24664350 
# 9  8  9 -0.06652047 -0.27798769 
# 10  9 10 -0.10424865 0.24060163 
3

Использование функций пола() и потолка(). И ifelse() в случаях, когда интервал составляет 1 - 1 или 2 - 2, например.

d<-data.frame(v1=seq(0,9.9,0.1), 
       v2=rnorm(100), 
       v3=rnorm(100))   

library(dplyr) 

d%>% 
     mutate(start=floor(v1), 
       end=ifelse(ceiling(v1)==start,start+1,ceiling(v1)))%>% 
     group_by(start,end)%>% 
     summarise(mean.v2=mean(v2), 
        mean.v3=mean(v3)) 

Source: local data frame [10 x 4] 
Groups: start [?] 

    start end  mean.v2  mean.v3 
    (dbl) (dbl)  (dbl)  (dbl) 
1  0  1 0.135180183 -0.36083298 
2  1  2 -0.245567899 0.26827020 
3  2  3 -0.051136441 0.14211666 
4  3  4 0.252451303 0.38530797 
5  4  5 0.007209073 0.30137345 
6  5  6 -0.307008690 0.07662942 
7  6  7 0.103271270 0.14734865 
8  7  8 0.016753997 -0.02559756 
9  8  9 -0.199958098 -0.21821830 
10  9 10 0.532339512 -0.46509108 

То же, но в том числе столбец с именем интервалы вместо двух (начало и конец):

d%>% 
     mutate(start=floor(v1), 
       end=ifelse(ceiling(v1)==start,start+1,ceiling(v1)), 
       interval=paste(start,"-",end))%>% 
     select(-start,-end)%>% 
     group_by(interval)%>% 
     summarise(mean.v2=mean(v2), 
        mean.v3=mean(v3)) 

Source: local data frame [10 x 3] 

    interval  mean.v2  mean.v3 
     (chr)  (dbl)  (dbl) 
1  0 - 1 0.135180183 -0.36083298 
2  1 - 2 -0.245567899 0.26827020 
3  2 - 3 -0.051136441 0.14211666 
4  3 - 4 0.252451303 0.38530797 
5  4 - 5 0.007209073 0.30137345 
6  5 - 6 -0.307008690 0.07662942 
7  6 - 7 0.103271270 0.14734865 
8  7 - 8 0.016753997 -0.02559756 
9  8 - 9 -0.199958098 -0.21821830 
10 9 - 10 0.532339512 -0.46509108 
+0

OP хотел, чтобы первый интервал был 0-0,99. Этот код исключает 1 из первого интервала, потому что 'floor (1) == ceiling (1)'. Это приятно, но менее прозрачно, чем использование функции 'cut()' с аргументом 'right'. –

+0

Вы правы, поэтому я использую функцию ifelse(). Когда вы получили 1 - 1, код интерпретируется как 2 - 1. Но вы также можете изменить код, чтобы он мог быть 0 - 1 (в функции ifelse). Код очень универсален. – Mario

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