# add a grouping variable
df$group = rep(1:50, each = 1000) # assumes 50 blocks of 1000 rows
Затем используйте dplyr
или data.table
, чтобы применить функцию по группе.Выберите ваш любимый:
library(dplyr)
df = df %>% group_by(group) %>% mutate(value_z = scale(value))
library(data.table)
setDT(df)
df[, value_z := scale(value), by = group]
Мы также можем использовать tapply
из базы R, но это делает больше предположений о ваших данных и может быть менее эффективным.(Это не будет работать так, как написано, если ваши данные еще не отсортированы по group
, другие методы все равно будут работать.)
df$value_z = unlist(with(df, tapply(X = value, INDEX = group, FUN = scale)))
Вот небольшой воспроизводимый пример, показывающий, что вы получаетеодинаковые результаты всех трех способов:
set.seed(47)
df = data.frame(time = rep(1:5, 3), value = rnorm(15))
df$group = rep(1:3, each = 5)
library(dplyr)
df = df %>% group_by(group) %>% mutate(value_z_dplyr = scale(value))
library(data.table)
setDT(df)
df[, value_z_dt := scale(value), by = group]
df$value_z_tapply = unlist(with(df, tapply(X = value, INDEX = group, FUN = scale)))
df
# time value group value_z_dplyr value_z_dt value_z_tapply
# 1: 1 1.99469634 1 1.6397422 1.6397422 1.6397422
# 2: 2 0.71114251 1 0.1892725 0.1892725 0.1892725
# 3: 3 0.18540528 1 -0.4048326 -0.4048326 -0.4048326
# 4: 4 -0.28176501 1 -0.9327546 -0.9327546 -0.9327546
# 5: 5 0.10877555 1 -0.4914274 -0.4914274 -0.4914274
# 6: 1 -1.08573747 2 -0.5379979 -0.5379979 -0.5379979
# 7: 2 -0.98548216 2 -0.3750263 -0.3750263 -0.3750263
# 8: 3 0.01513086 2 1.2515355 1.2515355 1.2515355
# 9: 4 -0.25204590 2 0.8172223 0.8172223 0.8172223
# 10: 5 -1.46575030 2 -1.1557336 -1.1557336 -1.1557336
# 11: 1 -0.92245624 3 -0.5283725 -0.5283725 -0.5283725
# 12: 2 0.03960243 3 0.4938015 0.4938015 0.4938015
# 13: 3 0.49382018 3 0.9764016 0.9764016 0.9764016
# 14: 4 -1.82822917 3 -1.4907437 -1.4907437 -1.4907437
# 15: 5 0.09147291 3 0.5489132 0.5489132 0.5489132