R change data using row with NA to identify new column

I have a dataset in R that looks like this:

DF <- data.frame(name=c("A","b","c","d","B","e","f"),
                 x=c(NA,1,2,3,NA,4,5))

      

I would like to change it to:

rDF <- data.frame(name=c("b","c","d","e","f"),
                  x=c(1,2,3,4,5),
                  head=c("A","A","A","B","B"))

      

where the first row c NA

identifies the new column and takes this "row value" until the next row c NA

and then modifies the "row value".

I've tried both spread

, melt

but it doesn't give me what I want.

library(tidyr)
DF %>% spread(name,x)
library(reshape2)
melt(DF, id=c('name'))

      

Any suggestions?

+3


source to share


3 answers


Here's a possible solution for the combination of packages data.table

/zoo

library(data.table) ; library(zoo)

setDT(DF)[is.na(x), head := name]
na.omit(DF[, head := na.locf(head)], "x")

#    name x head
# 1:    b 1    A
# 2:    c 2    A
# 3:    d 3    A
# 4:    e 4    B
# 5:    f 5    B

      



Or as suggested by @Arun, just using data.table

na.omit(setDT(DF)[, head := name[is.na(x)], by=cumsum(is.na(x))])

      

+5


source


You may try:



library(data.table)
library(magrittr)

split(DF, cumsum(is.na(DF$x))) %>%
    lapply(function(u) transform(u[-1,], head=u[1,1])) %>% 
    rbindlist

#   name x head
#1:    b 1    A
#2:    c 2    A
#3:    d 3    A
#4:    e 4    B
#5:    f 5    B

      

+3


source


Here's an approach using only basic R functions:

idx <- is.na(DF$x)
x <- rle(cumsum(idx))$lengths
DF$head <- rep(DF$name[idx], x)
DF[!idx,]
#  name x head
#2    b 1    A
#3    c 2    A
#4    d 3    A
#6    e 4    B
#7    f 5    B

      

+3


source







All Articles