我在几周内为一群人测量各种参数。我希望在治疗开始前将每个人的值标准化为第0天的个体值。示例data.frame:
id Day wt bp
a 0 10 100.00
b 0 15 120.00
c 0 12 150.00
a 1 7.5 120.00
b 1 10 150.00
c 1 8 175.00
b 2 5 110.00
c 2 4 140
所以个人" b"需要有他们的" wt"和" bp"第1天和第2天的值与第0天的值相比较。有些人辍学,因此数字会随着时间的推移而变化。规范化的data.frame看起来像这样:
id Day wt bp
a 0 100.0 100.0
b 0 100.0 100.0
c 0 100.0 100.0
a 1 75.0 120.0
b 1 66.7 125.0
c 1 66.7 116.7
b 2 33.3 91.7
c 2 33.3 93.3
我可以通过逐步浏览每一天/一个ID来实现,但似乎应该有一种方法可以使用其中一个apply
变体。
答案 0 :(得分:3)
也许这样:
library(tidyverse)
df %>%
group_by(id) %>%
mutate(wt_norm = wt/wt[Day == 0]*100,
bp_norm = bp/bp[Day == 0]*100)
#output
# A tibble: 8 x 6
# Groups: id [3]
id Day wt bp wt_norm bp_norm
<fct> <int> <dbl> <dbl> <dbl> <dbl>
1 a 0 10.0 100 100 100
2 b 0 15.0 120 100 100
3 c 0 12.0 150 100 100
4 a 1 7.50 120 75.0 120
5 b 1 10.0 150 66.7 125
6 c 1 8.00 175 66.7 117
7 b 2 5.00 110 33.3 91.7
8 c 2 4.00 140 33.3 93.3
或@C的建议。布朗在评论中说:
df %>%
group_by(id) %>%
mutate(wt_norm = wt/first(wt)*100,
bp_norm = bp/first(bp)*100)
或@iayork在评论中的建议:
df %>%
group_by(id) %>%
transmute_at(vars(-Day),funs(./first(.)*100))
数据:
df <- read.table(text = "id Day wt bp
a 0 10 100.00
b 0 15 120.00
c 0 12 150.00
a 1 7.5 120.00
b 1 10 150.00
c 1 8 175.00
b 2 5 110.00
c 2 4 140", header = T)
答案 1 :(得分:1)
如果您在data.frame中有更多列,则可以使用mutate_at()
require(tidyverse)
set.seed(123)
df <- data.frame(id = rep(c("a","b","c")),
day = c(rep(0, 3), rep(1, 3), rep(2, 3)),
wt = rnorm(9, mean = 10, sd = 2),
bp = rnorm(9, mean = 120, sd = 10))
df %>%
group_by(id) %>%
mutate_at(vars(-day),funs(varNorm = ./first(.)*100))