问题描述:

I have a dataset like this:

df=data.frame(subject= c(rep(1, 3), rep(2, 2),rep(3,4)), visit=c(1:3,1:2,1:4),time=c('2003-03-07 6:34','2003-03-07 7:33','2003-03-07 8:15','2003-03-15 6:42','2003-03-15 7:42','2003-03-16 6:20','2003-03-16 6:40','2003-03-16 7:38','2003-03-16 8:42'))

subject visit time

1 1 1 2003-03-07 6:34

2 1 2 2003-03-07 7:33

3 1 3 2003-03-07 8:15

4 2 1 2003-03-15 6:42

5 2 2 2003-03-15 7:42

6 3 1 2003-03-16 6:20

7 3 2 2003-03-16 6:40

8 3 3 2003-03-16 7:38

9 3 4 2003-03-16 8:42

I wish to create a column so that it contains the baseline time for each individual at each visit, the expected output should look like this:

df1=data.frame(subject= c(rep(1, 3), rep(2, 2),rep(3,4)), visit=c(1:3,1:2,1:4),time=c('2003-03-07 6:34','2003-03-07 6:34','2003-03-07 6:34','2003-03-15 6:42','2003-03-15 6:42','2003-03-16 6:20','2003-03-16 6:20','2003-03-16 6:20','2003-03-16 6:20'))

subject visit time

1 1 1 2003-03-07 6:34

2 1 2 2003-03-07 6:34

3 1 3 2003-03-07 6:34

4 2 1 2003-03-15 6:42

5 2 2 2003-03-15 6:42

6 3 1 2003-03-16 6:20

7 3 2 2003-03-16 6:20

8 3 3 2003-03-16 6:20

9 3 4 2003-03-16 6:20

Does anyone have any idea on how to realized this?

网友答案:

Option 1 (assume sort order):

do.call(rbind, lapply(split(df, df$subject), function(x) cbind(x,time2 = with(x, x$time[1]))))

Option 2 (a slightly more robust solution that figures out which is the first visit):

do.call(rbind, lapply(split(df, df$subject), function(x) cbind(x,time2 = with(x, x$time[which(x$visit==1)]))))

Option 3 (convert to POSIXct and use min):

do.call(rbind, lapply(split(df, df$subject), function(x) cbind(x,time2 = min(as.POSIXct(x$time)))))

Option 4 (probably fastest/easiest):

within(df, time2 <- ave(as.POSIXct(time), subject, FUN = min))

Option 5 (again assume sort order):

within(df, time2 <- ave(time, subject, FUN = function(x) head(x, 1)))

All of these will give you:

    subject visit            time           time2
1.1       1     1 2003-03-07 6:34 2003-03-07 6:34
1.2       1     2 2003-03-07 7:33 2003-03-07 6:34
1.3       1     3 2003-03-07 8:15 2003-03-07 6:34
2.4       2     1 2003-03-15 6:42 2003-03-15 6:42
2.5       2     2 2003-03-15 7:42 2003-03-15 6:42
3.6       3     1 2003-03-16 6:20 2003-03-16 6:20
3.7       3     2 2003-03-16 6:40 2003-03-16 6:20
3.8       3     3 2003-03-16 7:38 2003-03-16 6:20
3.9       3     4 2003-03-16 8:42 2003-03-16 6:20
网友答案:

data.table approach

library(data.table)
setDT(df)[, time2 := min(as.POSIXct(time)), by = subject]

dplyr approach

library(dplyr)
df %>%
  group_by(subject) %>%
  mutate(time = min(as.POSIXct(time)))
网友答案:

You can use dplyr for this.

require(dplyr)

df %>%
  group_by(subject) %>%
  summarize(time2 = time[1]) %>%
  left_join(df, by = "subject")

Here's the resulting data frame:

  subject           time2 visit            time
1       1 2003-03-07 6:34     1 2003-03-07 6:34
2       1 2003-03-07 6:34     2 2003-03-07 7:33
3       1 2003-03-07 6:34     3 2003-03-07 8:15
4       2 2003-03-15 6:42     1 2003-03-15 6:42
5       2 2003-03-15 6:42     2 2003-03-15 7:42
6       3 2003-03-16 6:20     1 2003-03-16 6:20
7       3 2003-03-16 6:20     2 2003-03-16 6:40
8       3 2003-03-16 6:20     3 2003-03-16 7:38
9       3 2003-03-16 6:20     4 2003-03-16 8:42
相关阅读:
Top