-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathglimpse.R
205 lines (169 loc) · 5.1 KB
/
glimpse.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#' Get a glimpse of your data
#'
#' The `tibble` S3 generic function [pillar::glimpse()] is implemented for
#' `prt` objects as well. Inspired by the output of [str()] when applied to
#' `data.frames`, this function is intended to display the structure of the
#' data in terms of columns, irrespective of how the data is organized in terms
#' of `R` objects. Similarly to [format_dt()], the function providing the bulk
#' of functionality, `glimpse_dt()`, is exported such that implementing a
#' class specific [pillar::glimpse()] function for other classes that
#' representing tabular data is straightforward.
#'
#' Alongside a `prt`-specific [pillar::glimpse()] method, a [str()] method is
#' provided as well for `prt` objects. However, breaking with base `R`
#' expectations, it is not the structure of the object in terms of `R` objects
#' that is shown, but in the same spirit as [pillar::glimpse()] it is the
#' structure of the data that is printed. How this data is represents with
#' respect to `R` objects is abstracted away as to show output as would be
#' expected if the data were represented by a `data.frame`.
#'
#' In similar spirit as [format_dt()] and `glimpse_dt()`, a `str_dt()` function
#' is exported which provides the core functionality driving the `prt`
#' implementation of [str()]. This function requires availability of a
#' [head()] function for any object that is passed and output can be
#' customized by implementing an optional `str_sum()` function.
#'
#' @examples
#' cars <- as_prt(mtcars)
#'
#' pillar::glimpse(cars)
#' pillar::glimpse(cars, width = 30)
#'
#' str(cars)
#' str(cars, vec.len = 1)
#'
#' str(unclass(cars))
#'
#' str_sum(cars)
#'
#' @inheritParams pillar::glimpse
#'
#' @rdname glimpse
#'
#' @importFrom tibble glimpse
#' @importFrom pillar new_pillar_title new_pillar_type
#'
#' @export
#'
glimpse.prt <- function(x, width = NULL, ...) {
glimpse_dt(x = x, width = width)
invisible(x)
}
#' @rdname glimpse
#'
#' @export
#'
glimpse_dt <- function(x, width = NULL) {
width <- print_width(width, allow_inf = FALSE)
if (!is.finite(width)) {
abort("`glimpse()` requires a finite value for the `width` argument.",
"err_glimp_inf_width")
}
cat_line("Rows: ", big_mark(nrow(x)))
rows <- as.integer(width / 3)
df <- as.data.frame(head(x, rows))
cat_line("Columns: ", big_mark(ncol(df)))
summary <- tbl_sum(x)
brief_summary <- summary[-1]
if (length(brief_summary) > 0L) {
cat_line(names(brief_summary), ": ", brief_summary)
}
if (ncol(df) == 0) return(invisible(x))
var_types <- vapply(lapply(df, new_pillar_type), format, character(1L))
ticked_names <- format(new_pillar_title(tick_if_needed(names(df))))
var_names <- paste0("$ ", justify(ticked_names, right = FALSE), " ",
var_types, " ")
data_width <- width - crayon::col_nchar(var_names) - 2
formatted <- vapply(df, function(x) collapse(format_row(x)), character(1L))
truncated <- str_trunc(formatted, data_width)
if (!crayon::has_color()) {
var_names <- crayon::strip_style(var_names)
}
cat_line(var_names, truncated)
invisible(NULL)
}
format_row <- function(x) UseMethod("format_row")
#' @export
format_row.default <- function(x) {
dims <- dim(x)
if (!is.null(dims)){
dims_out <- paste0(dims, collapse = " x ")
out <- paste0("<", class(x)[1], "[", dims_out, "]>")
out
} else {
format(x, trim = TRUE, justify = "none")
}
}
#' @export
format_row.character <- function(x) encodeString(x, quote = '"')
#' @export
format_row.factor <- function(x) {
if (any(grepl(",", x, fixed = TRUE))) {
encodeString(as.character(x), quote = '"')
} else {
format(x, trim = TRUE, justify = "none")
}
}
#' @rdname glimpse
#'
#' @export
#'
str_sum <- function(x) UseMethod("str_sum")
#' @export
str_sum.prt <- function(x) {
ncol <- ncol(x)
cls <- paste0("'", class(x), "'", collapse = ", ")
npart <- n_part(x)
paste0(
cls, ":\t", nrow(x), " obs. of ", ncol, " variable", if (ncol != 1) "s",
" in ", npart, " partition", if (npart != 1) "s", if (ncol > 0) ":", "\n"
)
}
#' @export
str_sum.data.frame <- function(x) {
ncol <- ncol(x)
cls <- paste0("'", class(x), "'", collapse = ", ")
paste0(
cls, ":\t", nrow(x), " obs. of ", ncol, " variable", if (ncol != 1) "s\n"
)
}
#' @inheritParams utils::str
#'
#' @rdname glimpse
#'
#' @importFrom utils str
#'
#' @export
#'
str.prt <- function(object, ...) {
invisible(str_dt(object, ...))
}
#' @rdname glimpse
#'
#' @importFrom utils capture.output
#'
#' @export
#'
str_dt <- function(x, ...) {
dots <- list(...)
if ("vec.len" %in% names(dots)) {
len <- dots[["vec.len"]]
} else {
len <- utils::strOptions()$vec.len
}
dat <- head(x, len * 3L + 1L)
if (!"give.length" %in% names(dots)) {
dots[["give.length"]] <- FALSE
}
dots[["no.list"]] <- TRUE
cat(str_sum(x))
if (isTRUE(dots[["give.length"]]) && nrow(dat) > 0L) {
res <- capture.output(do.call("str", c(list(c(dat)), dots)))
res <- sub(paste0("\\[1:", nrow(dat), "\\]"),
paste0( "[1:", nrow(x), "]"), res)
cat_line(res)
} else {
do.call("str", c(list(c(dat)), dots))
}
invisible()
}