Reputation: 325
I have a dataframe where data are sorted like that:
df <- data.frame('a'= c('b'), 'c'=c('d'), 'e'= c('f'), 'g'= c('h'), 'i'=c('j'))
df
# a c e g i
# 1 b d f h j
Is there a way that I can transform the dataframe, so data move one row down (lineary) for each column? Except from the first row where the value stays where it is:
df_expected <- data.frame('a'= c('b', '','','',''), 'c'=c('','d','','',''), 'e'= c('', '', 'f', '',''), 'g'= c('','','','h',''), 'i'=c('','','','','j'))
df_expected
# a c e g i
# 1 b
# 2 d
# 3 f
# 4 h
# 5 j
Upvotes: 2
Views: 119
Reputation: 101257
You can try
`diag<-`(matrix("", length(df), length(df)), unlist(df))
or
replace(u <- `diag<-`(diag(length(df)), unlist(df)), u == "0", "")
which gives
[,1] [,2] [,3] [,4] [,5]
[1,] "b" "" "" "" ""
[2,] "" "d" "" "" ""
[3,] "" "" "f" "" ""
[4,] "" "" "" "h" ""
[5,] "" "" "" "" "j"
Upvotes: 1
Reputation: 36
For your specific data frame, using diag()
is much easier. The following code should work in general cases.
df_expected <- matrix(0, ncol = ncol(df), nrow = nrow(df) + ncol(df) - 1)
df_expected[1:length(df[,1]),1] <- df[,1]
for(i in 2:ncol(df)){
tmp <- c(rep(0, i-1), df[, i])
df_expected[1:i,i] <- tmp
}
df_expected <- as.data.frame(df_expected)
names(df_expected) <- names(df)
Upvotes: 1
Reputation: 887078
We can use diag
m1 <- diag(ncol(df))
m1[m1 == 1] <- unlist(df)
as.data.frame(m1)
Or create a matrix
m2 <- matrix('', ncol = ncol(df), nrow = ncol(df),
dimnames = list(NULL, names(df)))
m2[upper.tri(m2) == lower.tri(m2)] <- unlist(df)
Upvotes: 3