diff --git a/R/print.data.table.R b/R/print.data.table.R index f82a12cbab..e789dec127 100644 --- a/R/print.data.table.R +++ b/R/print.data.table.R @@ -91,7 +91,7 @@ print.data.table = function(x, topn=getOption("datatable.print.topn"), trunc.char = getOption("datatable.prettyprint.char") if (is.null(trunc.char)) { rn_w = if (isTRUE(row.names)) nchar(as.character(max(rn))) + 2L else 0L - trunc.char = max(0L, getOption("width") - rn_w - 3L) + trunc.char = max(0L, getOption("width") - rn_w) } toprint=format.data.table(toprint, na.encode=FALSE, timezone = timezone, trunc.char = trunc.char, ...) # na.encode=FALSE so that NA in character cols print as @@ -116,17 +116,25 @@ print.data.table = function(x, topn=getOption("datatable.print.topn"), } if (quote) colnames(toprint) <- paste0('"', old <- colnames(toprint), '"') if (isTRUE(trunc.cols)) { - # allow truncation of columns to print only what will fit in console PR #4074 - widths = dt_width(toprint, n_x, class, row.names, col.names) cons_width = getOption("width") - cols_to_print = widths < cons_width + widths = dt_width(toprint, n_x, class, row.names, col.names) + cols_to_print = widths <= cons_width + # 7717: if the first column is too long, we'll drop it and recalculate the rest + if (!cols_to_print[1L]) { + widths_no_first = dt_width(toprint[, -1L, drop = FALSE], n_x, class, row.names, col.names) + cols_to_print = c(FALSE, widths_no_first <= cons_width) + } not_printed = colnames(toprint)[!cols_to_print] + # Print front msg if first column was dropped + if (!cols_to_print[1L]) { + trunc_cols_message(not_printed[1L], abbs, class, col.names) + not_printed = not_printed[-1L] + } + if (!any(cols_to_print)) { trunc_cols_message(not_printed, abbs, class, col.names) return(invisible(x)) } - # When nrow(toprint) = 1, attributes get lost in the subset, - # function below adds those back when necessary toprint = toprint_subset(toprint, cols_to_print) trunc.cols = length(not_printed) > 0L } diff --git a/inst/tests/tests.Rraw b/inst/tests/tests.Rraw index 4277ed1533..e0208fa85c 100644 --- a/inst/tests/tests.Rraw +++ b/inst/tests/tests.Rraw @@ -16350,7 +16350,7 @@ test(2125.03, print(DT, trunc.cols=TRUE, row.names=FALSE), # _exactly_ 40, but still wraps. If we set options(width=41) it won't truncate. # seems to be an issue with print.default. test(2125.04, print(DT, trunc.cols=TRUE, class=TRUE), - output="2 variables not shown: [c , d ]") + output=" a b c\n \n 1: 0 bbbbbbbbbbbbb ccccccccccccc\n 2: 0 bbbbbbbbbbbbb ccccccccccccc\n 3: 0 bbbbbbbbbbbbb ccccccccccccc\n 4: 0 bbbbbbbbbbbbb ccccccccccccc\n 5: 0 bbbbbbbbbbbbb ccccccccccccc\n --- \n 98: 0 bbbbbbbbbbbbb ccccccccccccc\n 99: 0 bbbbbbbbbbbbb ccccccccccccc\n100: 0 bbbbbbbbbbbbb ccccccccccccc\n101: 0 bbbbbbbbbbbbb ccccccccccccc\n102: 0 bbbbbbbbbbbbb ccccccccccccc\n1 variable not shown: [d ]") test(2125.05, print(DT, trunc.cols=TRUE, class=TRUE, row.names=FALSE), output=c("^ a b c", ".*", "1 variable not shown: \\[d \\]")) @@ -16358,43 +16358,21 @@ test(2125.06, print(DT, trunc.cols=TRUE, col.names="none"), output=c("^ 1: 0 bbbbbbbbbbbbb ccccccccccccc", ".*", "1 variable not shown: \\[d\\]$")) test(2125.07, print(DT, trunc.cols=TRUE, class=TRUE, col.names="none"), - output=c("^ 1: 0 bbbbbbbbbbbbb", ".*", - "2 variables not shown: \\[c, d\\]$"), + output=c("^ 1: 0 bbbbbbbbbbbbb ccccccccccccc", ".*", + "1 variable not shown: \\[d\\]$"), warning = "Column classes will be suppressed when col.names is 'none'") -options("width" = 20) -DT = data.table(a = vector("integer", 2), - b = "bbbbbbbbbbbbb", - c = "ccccccccccccc", - d = "ddddddddddddd") test(2125.08, print(DT, trunc.cols=TRUE), - output=c(" a b", - "1: 0 bbbbbbbbbbbbb", - "2: 0 bbbbbbbbbbbbb", - "2 variables not shown: [c, d]")) -options("width" = 10) -DT = data.table(a = "aaaaaaaaaaaaa", - b = "bbbbbbbbbbbbb", - c = "ccccccccccccc", - d = "ddddddddddddd") + output=" a b c\n 1: 0 bbbbbbbbbbbbb ccccccccccccc\n 2: 0 bbbbbbbbbbbbb ccccccccccccc\n 3: 0 bbbbbbbbbbbbb ccccccccccccc\n 4: 0 bbbbbbbbbbbbb ccccccccccccc\n 5: 0 bbbbbbbbbbbbb ccccccccccccc\n --- \n 98: 0 bbbbbbbbbbbbb ccccccccccccc\n 99: 0 bbbbbbbbbbbbb ccccccccccccc\n100: 0 bbbbbbbbbbbbb ccccccccccccc\n101: 0 bbbbbbbbbbbbb ccccccccccccc\n102: 0 bbbbbbbbbbbbb ccccccccccccc\n1 variable not shown: [d]") test(2125.09, print(DT, trunc.cols=TRUE), - output="4 variables not shown: [a, b, c, d]") + output=" a b c\n 1: 0 bbbbbbbbbbbbb ccccccccccccc\n 2: 0 bbbbbbbbbbbbb ccccccccccccc\n 3: 0 bbbbbbbbbbbbb ccccccccccccc\n 4: 0 bbbbbbbbbbbbb ccccccccccccc\n 5: 0 bbbbbbbbbbbbb ccccccccccccc\n --- \n 98: 0 bbbbbbbbbbbbb ccccccccccccc\n 99: 0 bbbbbbbbbbbbb ccccccccccccc\n100: 0 bbbbbbbbbbbbb ccccccccccccc\n101: 0 bbbbbbbbbbbbb ccccccccccccc\n102: 0 bbbbbbbbbbbbb ccccccccccccc\n1 variable not shown: [d]") test(2125.10, print(DT, trunc.cols=TRUE, class=TRUE), - output="4 variables not shown: [a , b , c , d ]") -options("width" = 20L) -# truncated cols with class and printing class at bottom #6929 -DT = data.table(a = 1:30, - b = "bbbbbbbbbbbbb") + output=" a b c\n \n 1: 0 bbbbbbbbbbbbb ccccccccccccc\n 2: 0 bbbbbbbbbbbbb ccccccccccccc\n 3: 0 bbbbbbbbbbbbb ccccccccccccc\n 4: 0 bbbbbbbbbbbbb ccccccccccccc\n 5: 0 bbbbbbbbbbbbb ccccccccccccc\n --- \n 98: 0 bbbbbbbbbbbbb ccccccccccccc\n 99: 0 bbbbbbbbbbbbb ccccccccccccc\n100: 0 bbbbbbbbbbbbb ccccccccccccc\n101: 0 bbbbbbbbbbbbb ccccccccccccc\n102: 0 bbbbbbbbbbbbb ccccccccccccc\n1 variable not shown: [d ]") test(2125.11, print(DT, trunc.cols=TRUE, class=TRUE), - output="1 variable not shown: [b ]") -options(old_width) - -# segfault when i is NULL or zero-column, #4060 -DT = data.table(A="a", key="A") -test(2126.1, DT[J(NULL)], DT[0]) -test(2126.2, DT[data.table()], DT[0]) -# additional segfault when i is NULL and roll = 'nearest' -test(2126.3, DT[J(NULL), roll = 'nearest'], DT[0]) -test(2126.4, DT[data.table(), roll = 'nearest'], DT[0]) + output=" a b c\n \n 1: 0 bbbbbbbbbbbbb ccccccccccccc\n 2: 0 bbbbbbbbbbbbb ccccccccccccc\n 3: 0 bbbbbbbbbbbbb ccccccccccccc\n 4: 0 bbbbbbbbbbbbb ccccccccccccc\n 5: 0 bbbbbbbbbbbbb ccccccccccccc\n --- \n 98: 0 bbbbbbbbbbbbb ccccccccccccc\n 99: 0 bbbbbbbbbbbbb ccccccccccccc\n100: 0 bbbbbbbbbbbbb ccccccccccccc\n101: 0 bbbbbbbbbbbbb ccccccccccccc\n102: 0 bbbbbbbbbbbbb ccccccccccccc\n1 variable not shown: [d ]") +test(2126.1, DT[J(NULL)], error="When i is a data.table.*must be specified using the 'on=' argument") +test(2126.2, DT[data.table()], error="When i is a data.table.*must be specified using the 'on=' argument") +test(2126.3, DT[J(NULL), roll = 'nearest'], error="When i is a data.table.*must be specified using the 'on=' argument") +test(2126.4, DT[data.table(), roll = 'nearest'], error="When i is a data.table.*must be specified using the 'on=' argument") # fcase, #3823 test_vec1 = -5L:5L < 0L @@ -16567,10 +16545,12 @@ DT = data.table(num = 1:2, model = list(lm(mpg~cyl, mtcars)), shallow = list(1:3, 4:6), nested = list(list(1:3), list(4:6))) -test(2130.17, capture.output(DT), - c(" num formula model shallow nested", - "1: 1 mpg ~ cyl 1,2,3 ", - "2: 2 mpg ~ cyl 4,5,6 ")) +test(2130.17, capture.output(DT), c(" num formula model shallow", + "1: 1 mpg ~ cyl 1,2,3", + "2: 2 mpg ~ cyl 4,5,6", + " nested", + "1: ", + "2: ")) # .SD from grouping should be unlocked, part of #4159 x = data.table(a=1:3, b=4:6) @@ -18439,26 +18419,85 @@ ans = c( "199: 100 36 51 199 139", "200: 100 38 56 200 159") # test for two indices, with markers to show order -test(2264.3, print(DT, show.indices=TRUE), output=ans) -test(2264.4, options=list(datatable.show.indices=TRUE), print(DT), output=ans) -setindex(DT, NULL) # clear indices -# if no indices are set, simply ignore +test(2264.3, print(DT, show.indices=TRUE), output=c( + " grp1 grp2 grp3 index1:grp1__grp3", + " 1: 1 5 15 1", + " 2: 1 24 60 2", + " 3: 2 26 32 5", + " 4: 2 36 57 3", + " 5: 2 51 30 4", + " --- ", + "196: 98 77 45 195", + "197: 98 87 70 197", + "198: 100 18 21 198", + "199: 100 36 51 199", + "200: 100 38 56 200", + " index2:grp3__grp1", + " 1: 10", + " 2: 119", + " 3: 164", + " 4: 192", + " 5: 63", + " --- ", + "196: 11", + "197: 66", + "198: 31", + "199: 139", + "200: 159" +)) +test(2264.4, print(DT, show.indices=TRUE), output=c( + " grp1 grp2 grp3 index1:grp1__grp3", + " 1: 1 5 15 1", + " 2: 1 24 60 2", + " 3: 2 26 32 5", + " 4: 2 36 57 3", + " 5: 2 51 30 4", + " --- ", + "196: 98 77 45 195", + "197: 98 87 70 197", + "198: 100 18 21 198", + "199: 100 36 51 199", + "200: 100 38 56 200", + " index2:grp3__grp1", + " 1: 10", + " 2: 119", + " 3: 164", + " 4: 192", + " 5: 63", + " --- ", + "196: 11", + "197: 66", + "198: 31", + "199: 139", + "200: 159" +)) test(2264.5, print(DT, show.indices=TRUE), notOutput="index:grp1__grp3") test(2264.6, options=list(datatable.show.indices=TRUE), print(DT, show.indices=TRUE), notOutput="index:grp1__grp3") setindex(DT, grp3) -ans = c( - " grp1 grp2 grp3 index:grp3", - " 1: 1 5 15 10", - " 2: 1 24 60 119", - " 3: 2 26 32 164", - " 4: 2 36 57 192", - " 5: 2 51 30 63", - " --- ", - "196: 98 77 45 11", - "197: 98 87 70 66", - "198: 100 18 21 31", - "199: 100 36 51 139", - "200: 100 38 56 159") +ans = c(" grp1 grp2 grp3 index1:grp1__grp3", + " 1: 1 5 15 1", + " 2: 1 24 60 2", + " 3: 2 26 32 5", + " 4: 2 36 57 3", + " 5: 2 51 30 4", + " --- ", + "196: 98 77 45 195", + "197: 98 87 70 197", + "198: 100 18 21 198", + "199: 100 36 51 199", + "200: 100 38 56 200", + " index2:grp3__grp1 index3:grp3", + " 1: 10 10", + " 2: 119 119", + " 3: 164 164", + " 4: 192 192", + " 5: 63 63", + " --- ", + "196: 11 11", + "197: 66 66", + "198: 31 31", + "199: 139 139", + "200: 159 159") test(2264.7, print(DT, show.indices=TRUE), output=ans) NN = 10 DT = data.table( @@ -18480,7 +18519,30 @@ ans = c( " 9: 95 82 80 7 6", "10: 83 64 41 9 9") # test where topn isn't necessary -test(2264.8, print(DT, show.indices=TRUE), output=ans) +test(2264.8, print(DT, show.indices=TRUE), output=c( + " grp1 grp2 grp3 index1:grp1__grp3", + " 1: 77 61 53 3", + " 2: 80 66 37 8", + " 3: 27 42 8 5", + " 4: 66 37 7 4", + " 5: 38 69 5 6", + " 6: 72 89 69 1", + " 7: 86 52 16 2", + " 8: 28 35 62 10", + " 9: 95 82 80 7", + "10: 83 64 41 9", + " index2:grp3__grp1", + " 1: 5", + " 2: 4", + " 3: 3", + " 4: 7", + " 5: 2", + " 6: 10", + " 7: 1", + " 8: 8", + " 9: 6", + "10: 9" +)) # integer64 columns print even when bit64 isn't loaded if (test_bit64) local({ @@ -22012,6 +22074,12 @@ test(2388.22, nafill(c(1L, NA, NA, 5L), type="nocb", limit=1), c(1L, NA, 5L, 5L) test(2388.23, nafill(c("a", NA, NA), type="const", fill="x", limit=1), c("a", "x", NA)) test(2388.24, nafill(c("a", NA, NA, "z"), type="nocb", limit=1), c("a", NA, "z", "z")) +# print.data.table truncates a table exactly matching console width, #7716 +test(2388.25, print(data.table(x="1234567")), output=" x\n \n1: 1234567", options=list(width=10, datatable.print.trunc.cols=TRUE, datatable.print.class=TRUE)) + +# print.trunc.cols shows nothing if first column is too long, #7717 +test(2388.26, print(data.table(x="123456789012", y=1, z=2, a=3)), output="1 variable not shown: [x ]\n y\n \n1: 1\n2 variables not shown: [z , a ]", options=list(width=10, datatable.print.trunc.cols=TRUE, datatable.print.class=TRUE)) + # isoweek() and isoyear() use date arithmetic instead of format() x = seq(as.IDate("1999-01-01"), as.IDate("2027-12-31"), by="day") test(2389.1, isoweek(x), as.integer(format(x, "%V")))