I have a dataframe
data <- data.frame(v=c(15,25,24), x_val=c(12,7,2), y_val=c(6,6,18))
I want the resulting data to look like this with the data repeated in rows a specified number of times (here 2 times).
v1 x1 y1 v2 x2 y2 v3 x3 y3
15 12 6 25 7 6 24 2 18
15 12 6 25 7 6 24 2 18
I managed to get the data all in one row with the right column names but I'm not sure how to extend the column to a specified length with the values repeated. Further, how can I do this without loops? I want to run this with a larger dataset which can be quite slow with loops.
My code is below which gives the values in a single row.
r=NULL
r<- as.data.frame(matrix(nrow=1, ncol=1))
n<-2
for (i in 1:nrow(data_subset)){
datainarow <- data_subset[i,]
r=cbind(r,as.data.frame(datainarow))
colnames(r)[n] <- paste0("v",i)
colnames(r)[n 1] <- paste0("x",i)
colnames(r)[n 2] <- paste0("y",i)
n <- n 3
}
Thank you!
CodePudding user response:
You can use uncount
in the tidyr package
If you already have your data in the single row format, just do:
n=4
data %>% tidyr::uncount(n)
# A tibble: 4 x 9
v1 v2 v3 x1 x2 x3 y1 y2 y3
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 15 25 24 12 7 2 6 6 18
2 15 25 24 12 7 2 6 6 18
3 15 25 24 12 7 2 6 6 18
4 15 25 24 12 7 2 6 6 18
Here is one way to get that result from initial three row data frame
library(tidyverse)
n=4
data %>%
rename_all(~c("v","x","y")) %>%
mutate(id = row_number()) %>%
pivot_wider(names_from = id, values_from = v:y,names_sep = "") %>%
uncount(n)
CodePudding user response:
This is a one-liner in base R
as.data.frame(t(as.vector(t(data))))[rep(1, 2),]
#> V1 V2 V3 V4 V5 V6 V7 V8 V9
#> 1 15 12 6 25 7 6 24 2 18
#> 1.1 15 12 6 25 7 6 24 2 18
Or if you wish to use the naming convention described, and have a more generalizable solution, you could use the following function:
expand_data <- function(data, reps) {
df <- as.data.frame(t(as.vector(t(data))))[rep(1, reps),]
names(df) <- paste(names(data), rep(seq(nrow(data)), each = nrow(data)), sep = "_")
rownames(df) <- NULL
df
}
which allows:
expand_data(data, 10)
v_1 x_val_1 y_val_1 v_2 x_val_2 y_val_2 v_3 x_val_3 y_val_3
1 15 12 6 25 7 6 24 2 18
2 15 12 6 25 7 6 24 2 18
3 15 12 6 25 7 6 24 2 18
4 15 12 6 25 7 6 24 2 18
5 15 12 6 25 7 6 24 2 18
6 15 12 6 25 7 6 24 2 18
7 15 12 6 25 7 6 24 2 18
8 15 12 6 25 7 6 24 2 18
9 15 12 6 25 7 6 24 2 18
10 15 12 6 25 7 6 24 2 18