Oney Kanta
Oney Kanta

Reputation: 53

Ifelse with dplyr in R

I would like to use dplyr in replacing NA value in the DV column of each ID with DV value at a specific time point within that individual:

I can not figure out how to do it with dplyr. Here is my dataset:

ID   TIME  DV
1      0   5
1      2   NA
1      4   4 
2      0   3
2      2   3
2      4   NA
3      0   7
3      2   NA
3      4   9

Expected output:

ID   TIME  DV
1      0   5
1      2   4
1      4   4 
2      0   3
2      2   3
2      4   3
3      0   7
3      2   9
3      4   9

Any suggestions are appreciated. Best,

Upvotes: 2

Views: 291

Answers (2)

akrun
akrun

Reputation: 887118

We could use fill after grouping by 'ID'

library(dplyr)
library(tidyr)
df1 %>%
   arrange(ID, TIME) %>%
   # or as @r2evans mentioned
   #arrange(ID, factor(TIME, levels = c(0, 2, 4))) %>%
   group_by(ID) %>%
   fill(DV, .direction = 'downup')
# A tibble: 9 x 3
# Groups:   ID [3]
#     ID  TIME    DV
#  <int> <int> <int>
#1     1     0     5
#2     1     2     4
#3     1     4     4
#4     2     0     3
#5     2     2     3
#6     2     4     3
#7     3     0     7
#8     3     2     9
#9     3     4     9

data

df1 <- structure(list(ID = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L), TIME = c(0L, 
2L, 4L, 0L, 2L, 4L, 0L, 2L, 4L), DV = c(5L, NA, 4L, 3L, 3L, NA, 
7L, NA, 9L)), class = "data.frame", row.names = c(NA, -9L))

Upvotes: 2

r2evans
r2evans

Reputation: 160447

I agree with @akrun that perhaps fill is a good fit in general, but your rules suggest handling things a little differently (since "updown" does not follow your rules).

library(dplyr)
# library(tidyr)
dat %>%
  tidyr::pivot_wider(id_cols = "ID", names_from = "TIME", values_from = "DV") %>%
  mutate(
    `2` = if_else(is.na(`2`), `4`, `2`),
    `4` = if_else(is.na(`4`), `0`, `4`)
  ) %>%
  tidyr::pivot_longer(-ID, names_to = "TIME", values_to = "DV")
# # A tibble: 9 x 3
#      ID TIME     DV
#   <int> <chr> <int>
# 1     1 0         5
# 2     1 2         4
# 3     1 4         4
# 4     2 0         3
# 5     2 2         3
# 6     2 4         3
# 7     3 0         7
# 8     3 2         9
# 9     3 4         9

It might help to visualize what this is doing by looking mid-pipe:

dat %>%
  tidyr::pivot_wider(id_cols = "ID", names_from = "TIME", values_from = "DV")
# # A tibble: 3 x 4
#      ID   `0`   `2`   `4`
#   <int> <int> <int> <int>
# 1     1     5    NA     4
# 2     2     3     3    NA
# 3     3     7    NA     9
dat %>%
  tidyr::pivot_wider(id_cols = "ID", names_from = "TIME", values_from = "DV") %>%
  mutate(
    `2` = if_else(is.na(`2`), `4`, `2`),
    `4` = if_else(is.na(`4`), `0`, `4`)
  )
# # A tibble: 3 x 4
#      ID   `0`   `2`   `4`
#   <int> <int> <int> <int>
# 1     1     5     4     4
# 2     2     3     3     3
# 3     3     7     9     9

Upvotes: 3

Related Questions