Skip to content

Commit 96c3e6a

Browse files
simplify format_col.default, allowing e.g. vctrs_list_of columns to print well (#6637)
* simplify format_col.default, allowing e.g. vctrs_list_of columns to print well * rm vestigial * Test formatting of sf geometry columns 'sf' is one of the few packages that uses a list column in a data.frame with a correctly working format() method. Since we disregard such methods now, test that the correct behaviour still happens thanks to the format() methods of the individual list items. * Test that format.<column>() is disregarded --------- Co-authored-by: Ivan K <krylov.r00t@gmail.com>
1 parent 41152fd commit 96c3e6a

File tree

4 files changed

+12
-5
lines changed

4 files changed

+12
-5
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@
7676
7777
16. `fread()` now handles the `na.strings` argument for quoted text columns, making it possible to specify `na.strings = '""'` and read empty quoted strings as `NA`s, [#6974](https://github.com/Rdatatable/data.table/issues/6974). Thanks to @AngelFelizR for the report and @aitap for the PR.
7878
79+
17. A data.table with a column of class `vctrs_list_of` (from package {vctrs}) prints as expected, [#5948](https://github.com/Rdatatable/data.table/issues/5948). Before, they could be printed messily, e.g. printing every entry in a nested data.frame. Thanks @jesse-smith for the report, @DavisVaughan and @r2evans for contributing, and @MichaelChirico for the PR.
80+
7981
### NOTES
8082
8183
1. Continued work to remove non-API C functions, [#6180](https://github.com/Rdatatable/data.table/issues/6180). Thanks Ivan Krylov for the PRs and for writing a clear and concise guide about the R API: https://aitap.codeberg.page/R-api/.

R/print.data.table.R

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,6 @@ has_format_method = function(x) {
199199
format_col.default = function(x, ...) {
200200
if (!is.null(dim(x)))
201201
"<multi-column>"
202-
else if (has_format_method(x) && length(formatted<-format(x, ...))==length(x))
203-
formatted #PR5224 motivated by package sf where column class is c("sfc_MULTIPOLYGON","sfc") and sf:::format.sfc exists
204202
else if (is.list(x))
205203
vapply_1c(x, format_list_item, ...)
206204
else

inst/tests/other.Rraw

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pkgs = c("ggplot2", "hexbin", "plyr", "dplyr", "caret", "zoo", "xts", "gdata", "nlme", "bit64", "knitr", "parallel", "sf", "nanotime", "R.utils", "yaml")
1+
pkgs = c("bit64", "caret", "dplyr", "gdata", "ggplot2", "hexbin", "knitr", "nanotime", "nlme", "parallel", "plyr", "R.utils", "sf", "vctrs", "xts", "yaml", "zoo")
22
# First expression of this file must be as above: .gitlab-ci.yml uses parse(,n=1L) to read one expression from this file and installs pkgs.
33
# So that these dependencies of other.Rraw are maintained in a single place.
44
# TEST_DATA_TABLE_WITH_OTHER_PACKAGES is off by default so this other.Rraw doesn't run on CRAN. It is run by GLCI, locally in dev, and by
@@ -221,6 +221,7 @@ test(14.2, {example('CJ', package='data.table', local=TRUE, echo=FALSE); TRUE})
221221
if (loaded[["sf"]]) { #2273
222222
DT = as.data.table(st_read(system.file("shape/nc.shp", package = "sf"), quiet=TRUE))
223223
test(15, DT[1:3, .(NAME, FIPS, geometry)], output="Ashe.*-81.4.*Surry.*-80.4")
224+
test(15.1, DT, output="MULTIPOLYGON (((") # make sure individual list items are formatted, #6637, #5224
224225

225226
dsf = sf::st_as_sf(data.table(x=1:10, y=1:10, s=sample(1:2, 10, TRUE)), coords=1:2)
226227
test(16, split(dsf, dsf$s), list(`1` = dsf[dsf$s == 1, ], `2` = dsf[dsf$s == 2, ]))
@@ -774,3 +775,9 @@ if (loaded[["nanotime"]]) {
774775
res <- tables(env=.e)
775776
test(32, res[, .(NAME,NROW,NCOL,MB)], data.table(NAME="DT",NROW=20000000L,NCOL=15L,MB=2288.0))
776777
rm(.e, res)
778+
779+
if (loaded[["vctrs"]]) {
780+
# vctrs::list_of() columns are treated the same as other list() columns
781+
DT = data.table(a = 1, b = list_of(mtcars))
782+
test(33, DT, output="<vctrs_list_of>.*<data\\.frame\\[32x11\\]>")
783+
}

inst/tests/tests.Rraw

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16800,15 +16800,15 @@ registerS3method("format_col", "complex", format_col.default)
1680016800
# then i) test 1610.1 fails if test.data.table() is rerun, ii) user display of complex data would be affected
1680116801
# did try wrapping with on.exit(,add=TRUE) but perhaps because this is a script that is sys.source'd, it ran straight away
1680216802

16803-
# format method for column takes predecedence over format method for each list item
16803+
# as of #6637, format individual list items but not the whole list
1680416804
registerS3method("format", "myclass2130", function(x, ...) paste0("<", class(x)[1L], ":", x$id, ">"))
1680516805
DT = data.table(row=1:2, objs=list(structure(list(id="foo"), class="myclass2130"), structure(list(id="bar"), class="myclass2130")))
1680616806
test(2130.13, print(DT), output="myclass2130:foo.*myclass2130:bar")
1680716807
setattr(DT$objs, "class", "foo2130")
1680816808
registerS3method("format", "foo2130", function(x, ...) "All hail foo")
1680916809
test(2130.14, print(DT), output="myclass2130:foo.*myclass2130:bar") # because length 1 from format but needs to be length(x)
1681016810
registerS3method("format", "foo2130", function(x, ...) rep("All hail foo",length(x)))
16811-
test(2130.15, print(DT), output="All hail foo") # e.g. sf:::format.sfc rather than sf:::format.sfg on each item
16811+
test(2130.15, print(DT), output="myclass2130:foo.*myclass2130:bar") # used to call format(column), not vapply_1c(column, format)
1681216812
setattr(DT$objs, "class", "bar2130_with_no_method")
1681316813
test(2130.16, print(DT), output="myclass2130:foo.*myclass2130:bar")
1681416814
registerS3method("format", "myclass2130", format.default)

0 commit comments

Comments
 (0)