Вычтите значение первого года из каждой сгруппированной строки во фрейме данных - PullRequest
0 голосов
/ 20 ноября 2018

Мне нужна помощь экспертов R в этом сообществе: set.seed (1234) x <- data.frame (id = 1: 5, value1 = sample (1: 5,5, replace = T), value2 = sample(1: 5,5), год = 1) y <- data.frame (id = 1: 5, значение1 = образец (1: 10,5), значение2 = образец (1: 5,5), год = 2) z <- data.frame (id = образец (1: 4,3), значение 1 = образец (1: 10,3), значение 2 = образец (1: 5,3), год = 3) f <- данные.фрейм (id = образец (1: 2,2), значение 1 = образец (1: 10,2), значение 2 = образец (1: 5,2), год = 4) <br>(df <- rbind (x,y, z, f)) df1 <- df [порядок (df $ id, df $ year),] df1 id значение1 значение2 год 1 1 4 1 1 10 1 2 1 2 4 3 1 3 3 4 2 4 1 1 22 3 2 2 1 3 3 2 10 1 4 3 4 5 1 3 3 5 2 3 7 5 3 4 4 2 1 4 9 2 2 5 5 3 1 5 7 4 2 </p>

Я хочу получить этовывод:

id value1 value2 year
 1     9     -3    2
 1     1      0    3
 1     2     -1    4
 2    -2      2    2
 2    -3      2    3
 2     6      0    4
 3    -1      0    2
 3     3      0    3
 4     5      0    2
 5     2      1    2

Спасибо за помощь!

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Рассмотрим by (функция для подмножества фрейма данных по фактору (ам)) и вызовите ее subset (для фильтрации года 1) и within (для пересчета столбцов). Оттуда by возвращает список фреймов данных, которые вы можете связать вместе с do.call(rbind, ...).

Данные

txt = 'id value1 value2 year
1      1      4    1
1     10      1    2
1      2      4    3
1      3      3    4
2      4      1    1
2      2      3    2
2      1      3    3
2     10      1    4
3      4      5    1
3      3      5    2
3      7      5    3
4      4      2    1
4      9      2    2
5      5      3    1
5      7      4    2'

df1 <- read.table(text=txt, header=TRUE)

Процесс

df_list <- by(df1, df1$id, function(sub){      
  subset(
         within(sub, {        
             value1 <- value1 - value1[[1]] 
             value2 <- value2 - value2[[1]]           
         }), 
         year > 1
  )      
})

new_df <- data.frame(do.call(rbind, unname(df_list)),
                     row.names = NULL)    
new_df

#    id value1 value2 year
# 1   1      9     -3    2
# 2   1      1      0    3
# 3   1      2     -1    4
# 4   2     -2      2    2
# 5   2     -3      2    3
# 6   2      6      0    4
# 7   3     -1      0    2
# 8   3      3      0    3
# 9   4      5      0    2
# 10  5      2      1    2
0 голосов
/ 20 ноября 2018

После группировки по 'id', используйте mutate_at, чтобы сделать разницу между значениями и где 'year' равен 1 в столбцах 'value', а затем filter из строк, имеющих 'year' как 1

library(dplyr)
df1 %>% 
   group_by(id) %>%
   mutate_at(vars(value1:value2), funs(. -.[year == 1])) %>% 
   filter(year!= 1)
# A tibble: 10 x 4
# Groups:   id [5]
#      id value1 value2  year
#   <int>  <int>  <int> <int>
# 1     1      9     -3     2
# 2     1      1      0     3
# 3     1      2     -1     4
# 4     2     -2      2     2
# 5     2     -3      2     3
# 6     2      6      0     4
# 7     3     -1      0     2
# 8     3      3      0     3
# 9     4      5      0     2
#10     5      2      1     2

Или аналогичная логика с data.table

library(data.table)
setDT(df1)[, (2:3) := lapply(.SD, function(x) x - x[year == 1]),
      by = id, .SDcols = value1:value2][year != 1]

В base R мы можем сделать

nm1 <- c('value1', 'value2')
df1[nm1] <- df1[nm1] -df1[df1$year==1, 
        nm1][rep(seq_along(unique(df1$id)), table(df1$id)),]
df1[df1$year != 1,]

data

df1 <- structure(list(id = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 
  3L, 4L, 4L, 5L, 5L), value1 = c(1L, 10L, 2L, 3L, 4L, 2L, 1L, 
 10L, 4L, 3L, 7L, 4L, 9L, 5L, 7L), value2 = c(4L, 1L, 4L, 3L, 
 1L, 3L, 3L, 1L, 5L, 5L, 5L, 2L, 2L, 3L, 4L), year = c(1L, 2L, 
  3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 1L, 2L, 1L, 2L)), class =
   "data.frame", row.names = c(NA, -15L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...