0

This question is a variant of "How to print a long column from a dataframe splited in two columns side by side" that unfortunately had no answer.
I have a data frame with few columns and many rows that I would like to print in a single page. The following example is the just the beginning of my dataset.

structure(list(depnais = c("01", "02", "03", "04", "05", "06", 
"07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", 
"18", "19", "21", "22", "23"), n = c(4051L, 5163L, 3323L, 
1176L, 1394L, 12624L, 2623L, 2194L, 1227L, 3266L, 3111L, 2528L, 
26737L, 7105L, 1096L, 3194L, 5173L, 2592L, 2323L, 5993L, 4952L, 
571L)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-23L), .Names = c("depnais", "n"))

I would like to output its contents as :

#   depnais     n depnais      n depnais      n depnais      n depnais      n depnais     n 
# 1 01       4051 02        5163 03        3323 04        1176 05        1394 06       12624
# 2 07       2623 08        2194 09        1227 10        3266 11        3111 12        2528
# 3 13      26737 14        7105 15        1096 16        3194 17        5173 18        2592
# 4 19       2323 21        5993 22        4952 23         571

Today, I split my data frame into two parts : one with a number of rows that is a multiple of the number of splits (6 here) and another with the remainder of the rows, then I reorder the first part.

df %>% group_by(depnais) %>% summarise(n=n()) %>% 
  filter(depnais<'96') %>%
  bind_cols(data.frame(g=rep(1:6,16))) %>%
  replyr::replyr_split("g") %>%
  purrr::reduce(bind_cols) %>% select(-matches("^g"))

And I print the two data frames separately.

But, actually I don't need the two data frames I make from the orginal one. So: is there a way to directly print the data frame, just specifying how many splits parts there should be?

Nicolas2
  • 2,170
  • 1
  • 6
  • 15

1 Answers1

1

The incarnation of dcast() can reshape multiple columns simultaneously. With subsequent reordering and renaming of columns this can be employed to reshape a data.frame with many rows into a wide format.

Row first order

as requested by the OP:

library(data.table)
# specify number of splits
n_splits <- 6
# reshape to wide format
wide <- as.data.table(df)[, rn := rep(1:.N, each = n_splits, length.out = .N)][
  , dcast(.SD, rn ~ rowid(rn), as.character, value.var = colnames(df), fill = "")][
    , rn := NULL][]
# reorder columns
setcolorder(wide, as.vector(outer(colnames(df), 1:n_splits, paste, sep = "_")))
# rename columns
setnames(wide, rep(colnames(df), n_splits))
wide
   depnais     n depnais    n depnais    n depnais    n depnais    n depnais     n
1:      01  4051      02 5163      03 3323      04 1176      05 1394      06 12624
2:      07  2623      08 2194      09 1227      10 3266      11 3111      12  2528
3:      13 26737      14 7105      15 1096      16 3194      17 5173      18  2592
4:      19  2323      21 5993      22 4952      23  571

Note, that the result is transposed as requested by the OP, e.g., rows 1 to 6 of df are printed horizontally across the first row of the split (row first order).

Incomplete rows in the split are handled automatically. All columns are coerced to character and missing values are filled with "".


This will work also for other splits, e.g., n_splits <- 4:

   depnais     n depnais     n depnais    n depnais    n
1:      01  4051      02  5163      03 3323      04 1176
2:      05  1394      06 12624      07 2623      08 2194
3:      09  1227      10  3266      11 3111      12 2528
4:      13 26737      14  7105      15 1096      16 3194
5:      17  5173      18  2592      19 2323      21 5993
6:      22  4952      23   571

Column first order

For the sake of completeness, column first order can be achieved with a slight modification when creating rn:

library(data.table)
# specify number of splits
n_splits <- 6
# reshape to wide format, fill by column (column first order)
wide <- as.data.table(df)[, rn := rep(1:ceiling(.N/n_splits), length.out = .N)][][
  , dcast(.SD, rn ~ rowid(rn), as.character, value.var = colnames(df), fill = "")][
    , rn := NULL][]
# reorder columns
setcolorder(wide, as.vector(outer(colnames(df), 1:n_splits, paste, sep = "_")))
# rename columns
setnames(wide, rep(colnames(df), n_splits))
wide
   depnais    n depnais     n depnais    n depnais     n depnais    n depnais    n
1:      01 4051      05  1394      09 1227      13 26737      17 5173      22 4952
2:      02 5163      06 12624      10 3266      14  7105      18 2592      23  571
3:      03 3323      07  2623      11 3111      15  1096      19 2323             
4:      04 1176      08  2194      12 2528      16  3194      21 5993

Data

The data originally provided by the OP returned a corrupt data frame warning. This on is corrected:

df <- structure(list(depnais = c("01", "02", "03", "04", "05", "06", 
"07", "08", "09", "10", "11", "12", "13", "14", "15", "16", "17", 
"18", "19", "21", "22", "23"), n = c(4051L, 5163L, 3323L, 1176L, 
1394L, 12624L, 2623L, 2194L, 1227L, 3266L, 3111L, 2528L, 26737L, 
7105L, 1096L, 3194L, 5173L, 2592L, 2323L, 5993L, 4952L, 571L)), class = c("tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -22L))
Community
  • 1
  • 1
Uwe
  • 41,420
  • 11
  • 90
  • 134