Drop the last value in dataframe, bind the row to the same dataframe with a zero in place for the first colum, repeat 100 times

Viewed 45

I have a dataframe 'data.frame': 1 obs. of 100 variables, I need to repeat this row 100 times, each time with a varying number of zeros in the first columns of n+1, or as many zeros as the index of the row-1. At the same time I need to drop the last values of the rows so that I end with a 100 by 100 dataframe.

The dataframe looks like this:

# A tibble: 1 x 1
  Mass_PM10_evdf$~ $Mass2 $Mass3 $Mass4 $Mass5 $Mass6 $Mass7 $Mass8 $Mass9
             <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1             5.48   11.1   11.3   11.4   11.6   11.7   11.9   12.1   12.2

and I made a short example of what I need the output to look like, just using the first 5 columns.

 sample$Mass1 $Mass2 $Mass3 $Mass4 $Mass5
         <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1         5.49  11.1   11.3   11.4   11.6 
2         0      5.49  11.1   11.3   11.4 
3         0      0      5.49  11.1   11.3 
4         0      0      0      5.49  11.1 
5         0      0      0      0      5.49

How can I do this in a more or less automatic way? I appreciate the help.

2 Answers

You can use lapply to repeat rows :

vec <- unlist(df)
n <- ncol(df)
new_data <- as.data.frame(do.call(rbind, lapply(n:1,
                           function(x) c(rep(0, n - x), head(vec, x)))))

#  Mass_PM10_evdf Mass2 Mass3 Mass4 Mass5 Mass6 Mass7 Mass8 Mass9
#1           5.48 11.10 11.30 11.40 11.60 11.70 11.90 12.10 12.20
#2           0.00  5.48 11.10 11.30 11.40 11.60 11.70 11.90 12.10
#3           0.00  0.00  5.48 11.10 11.30 11.40 11.60 11.70 11.90
#4           0.00  0.00  0.00  5.48 11.10 11.30 11.40 11.60 11.70
#5           0.00  0.00  0.00  0.00  5.48 11.10 11.30 11.40 11.60
#6           0.00  0.00  0.00  0.00  0.00  5.48 11.10 11.30 11.40
#7           0.00  0.00  0.00  0.00  0.00  0.00  5.48 11.10 11.30
#8           0.00  0.00  0.00  0.00  0.00  0.00  0.00  5.48 11.10
#9           0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  5.48

data

df <- structure(list(Mass_PM10_evdf = 5.48, Mass2 = 11.1, Mass3 = 11.3, 
Mass4 = 11.4, Mass5 = 11.6, Mass6 = 11.7, Mass7 = 11.9, Mass8 = 12.1, 
Mass9 = 12.2), class = "data.frame", row.names = "1")

In base R, we can construct the matrix directly with toeplitz, and then set the lower triangle values to 0

out <- toeplitz(unlist(df))
out[lower.tri(out)] <- 0
colnames(out) <- colnames(df)
out
#      Mass_PM10_evdf Mass2 Mass3 Mass4 Mass5 Mass6 Mass7 Mass8 Mass9
# [1,]           5.48 11.10 11.30 11.40 11.60 11.70 11.90 12.10 12.20
# [2,]           0.00  5.48 11.10 11.30 11.40 11.60 11.70 11.90 12.10
# [3,]           0.00  0.00  5.48 11.10 11.30 11.40 11.60 11.70 11.90
# [4,]           0.00  0.00  0.00  5.48 11.10 11.30 11.40 11.60 11.70
# [5,]           0.00  0.00  0.00  0.00  5.48 11.10 11.30 11.40 11.60
# [6,]           0.00  0.00  0.00  0.00  0.00  5.48 11.10 11.30 11.40
# [7,]           0.00  0.00  0.00  0.00  0.00  0.00  5.48 11.10 11.30
# [8,]           0.00  0.00  0.00  0.00  0.00  0.00  0.00  5.48 11.10
# [9,]           0.00  0.00  0.00  0.00  0.00  0.00  0.00  0.00  5.48

data

df <- structure(list(Mass_PM10_evdf = 5.48, Mass2 = 11.1, Mass3 = 11.3, 
Mass4 = 11.4, Mass5 = 11.6, Mass6 = 11.7, Mass7 = 11.9, Mass8 = 12.1, 
Mass9 = 12.2), class = "data.frame", row.names = "1")
Related