ykl
ykl

Reputation: 397

R Creating new row for every subject in the data frame

I would like to insert an additional row for every subject (ID) at TIME=0.

The added row should contain the same column values, except A and B which should be changed to 2 and -2 for all subjects. All other column values for each subject should remain the same. The following example illustrates what I want to do for one subject:

ID = c(1,1,1,1)
TIME = c(0,1, 2,3)
CONC= c(0,6,12,9)
A= c(1,2,2,2)
B=c(0,0,0,0)
C=c(1,0,0,0)
DF1 = data.frame(ID, TIME, CONC, A, B,C) 


#add row for every new ID with A now = 2 and B = -2. All other columns must remain the same.
ID = c(1,1,1,1,1)
TIME = c(0,0,1, 2,3)
CONC= c(0,0,6,12,9)
A= c(1,2,2,2,2)
B=c(0,-2,0,0,0)
C=c(1,1,0,0,0)
DF2 = data.frame(ID, TIME, CONC, A, B,C) 

The procedure should do this for all ID's in the dataframe.

Do any of you know of a smart way to do this? Any help would be much appreciated.

Upvotes: 0

Views: 481

Answers (2)

Thierry
Thierry

Reputation: 18487

It can be straightforward with dplyr

library(dplyr)
DF1 %>% 
  filter(TIME == 0) %>% # select everything at TIME = 0
  mutate(A = 2, B = -2) %>% # replace A with 2 and B with -2
  bind_rows(DF1) # append the original data

Upvotes: 2

Benjamin
Benjamin

Reputation: 17279

If you use this utility function, you can add the row you are describing. The general process is

  1. extract the rows where TIME == 0.
  2. Add your new row to the end of that subset
  3. Fill in missing values
  4. bind the result to the rows where TIME != 0.

library(dplyr)
insertRow0 <- function(D){
  id <- D$ID[1]

  bind_rows(filter(D, TIME == 0),
            data_frame(ID = id,
                       TIME = 0,
                       A = 2,
                       B = -2)) %>%
    zoo::na.locf() %>%
    bind_rows(filter(D, TIME != 0))
}

Running through this for each ID is then as simple as

DF1 %>%
  group_by(ID) %>%
  do(insertRow0(.))

Upvotes: 1

Related Questions