Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -1638,4 +1638,6 @@ rowwiseDT(

20. Some clarity is added to `?GForce` for the case when subtle changes to `j` produce different results because of differences in locale. Because `data.table` _always_ uses the "C" locale, small changes to queries which activate/deactivate GForce might cause confusingly different results when sorting is involved, [#5331](https://github.com/Rdatatable/data.table/issues/5331). The inspirational example compared `DT[, .(max(a), max(b)), by=grp]` and `DT[, .(max(a), max(tolower(b))), by=grp]` -- in the latter case, GForce is deactivated owing to the _ad-hoc_ column, so the result for `max(a)` might differ for the two queries. An example is added to `?GForce`. As always, there are several options to guarantee consistency, for example (1) use namespace qualification to deactivate GForce: `DT[, .(base::max(a), base::max(b)), by=grp]`; (2) turn off all optimizations with `options(datatable.optimize = 0)`; or (3) set your R session to always sort in C locale with `Sys.setlocale("LC_COLLATE", "C")` (or temporarily with e.g. `withr::with_locale()`). Thanks @markseeto for the example and @michaelchirico for the improved documentation.

21.`print.data.table()` with `trunc.cols=TRUE` now correctly prints tables that exactly match the console width, and drops the first column to print the remaining columns when the first column is too long, [#7716](https://github.com/Rdatatable/data.table/issues/7716) [#7717](https://github.com/Rdatatable/data.table/issues/7717). Thanks to @tdhock for reporting and @anmolsriwastava for fixing.

## data.table v1.14.10 (Dec 2023) back to v1.10.0 (Dec 2016) has been moved to [NEWS.1.md](https://github.com/Rdatatable/data.table/blob/master/NEWS.1.md)
20 changes: 14 additions & 6 deletions R/print.data.table.R
Original file line number Diff line number Diff line change
Expand Up @@ -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 <NA>

Expand All @@ -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
}
Expand Down
178 changes: 123 additions & 55 deletions inst/tests/tests.Rraw
Original file line number Diff line number Diff line change
Expand Up @@ -16350,51 +16350,29 @@ 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 <char>, d <char>]")
output=" a b c\n <int> <char> <char>\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 <char>]")
test(2125.05, print(DT, trunc.cols=TRUE, class=TRUE, row.names=FALSE),
output=c("^ a b c", ".*",
"1 variable not shown: \\[d <char>\\]"))
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 <char>, b <char>, c <char>, d <char>]")
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 <int> <char> <char>\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 <char>]")
test(2125.11, print(DT, trunc.cols=TRUE, class=TRUE),
output="1 variable not shown: [b <char>]")
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 <int> <char> <char>\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 <char>]")
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
Expand Down Expand Up @@ -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 <lm[12]> 1,2,3 <list[1]>",
"2: 2 mpg ~ cyl <lm[12]> 4,5,6 <list[1]>"))
test(2130.17, capture.output(DT), c(" num formula model shallow",
"1: 1 mpg ~ cyl <lm[12]> 1,2,3",
"2: 2 mpg ~ cyl <lm[12]> 4,5,6",
" nested",
"1: <list[1]>",
"2: <list[1]>"))

# .SD from grouping should be unlocked, part of #4159
x = data.table(a=1:3, b=4:6)
Expand Down Expand Up @@ -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(
Expand All @@ -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({
Expand Down Expand Up @@ -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 <char>\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 <num>]\n y\n <num>\n1: 1\n2 variables not shown: [z <num>, a <num>]", 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")))
Expand Down
Loading