diff --git a/NEWS.md b/NEWS.md index 9d0c5d3a29..6fde60ed02 100644 --- a/NEWS.md +++ b/NEWS.md @@ -50,6 +50,10 @@ * `unstack` now produces row and column keys in the order of their first appearance and has two new keyword arguments `allowmissing` and `allowduplicates` ([#2494](https://github.com/JuliaData/DataFrames.jl/pull/2494)) +* [PrettyTables.jl](https://github.com/ronisbr/PrettyTables.jl) is now the + default back-end to print DataFrames to text/plain; the print option + `splitcols` was removed and the output format was changed + ([#2429](https://github.com/JuliaData/DataFrames.jl/pull/2429)) ## New functionalities diff --git a/Project.toml b/Project.toml index c743385032..80b3b11d76 100644 --- a/Project.toml +++ b/Project.toml @@ -13,28 +13,17 @@ LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" Missings = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" PooledArrays = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" +PrettyTables = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" -Reexport = "189a3867-3050-52da-a836-e630ba90ab69" REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +Reexport = "189a3867-3050-52da-a836-e630ba90ab69" SortingAlgorithms = "a2af1166-a08f-5f64-846c-94a0d3cef48c" Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" -Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" TableTraits = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +Tables = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" Unicode = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" -[extras] -DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" -DataValues = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5" -Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" -Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" -Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" -Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" - -[targets] -test = ["DataStructures", "DataValues", "Dates", "Logging", "Random", "Test"] - [compat] -julia = "1" CategoricalArrays = "0.8.3" Compat = "3.17" DataAPI = "1.4" @@ -42,7 +31,20 @@ InvertedIndices = "1" IteratorInterfaceExtensions = "0.1.1, 1" Missings = "0.4.2" PooledArrays = "0.5" +PrettyTables = "0.10" Reexport = "0.1, 0.2" SortingAlgorithms = "0.1, 0.2, 0.3" -Tables = "1" TableTraits = "0.4, 1" +Tables = "1" +julia = "1" + +[extras] +DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +DataValues = "e7dc6d0d-1eca-5fa6-8ad6-5aecde8b7ea5" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +Logging = "56ddb016-857b-54e1-b83d-db4d58db5568" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[targets] +test = ["DataStructures", "DataValues", "Dates", "Logging", "Random", "Test"] diff --git a/src/DataFrames.jl b/src/DataFrames.jl index f3722f964d..a2d9acad7a 100644 --- a/src/DataFrames.jl +++ b/src/DataFrames.jl @@ -7,6 +7,7 @@ using Base.Sort, Base.Order, Base.Iterators using TableTraits, IteratorInterfaceExtensions import LinearAlgebra: norm using Markdown +using PrettyTables import DataAPI, DataAPI.All, @@ -53,6 +54,7 @@ export AbstractDataFrame, nrow, order, outerjoin, + PrettyTables, rename!, rename, repeat!, @@ -111,6 +113,7 @@ include("groupeddataframe/callprocessing.jl") include("groupeddataframe/fastaggregates.jl") include("groupeddataframe/complextransforms.jl") +include("abstractdataframe/prettytables.jl") include("abstractdataframe/show.jl") include("groupeddataframe/show.jl") include("dataframerow/show.jl") diff --git a/src/abstractdataframe/io.jl b/src/abstractdataframe/io.jl index 5035fbd247..5754571d72 100644 --- a/src/abstractdataframe/io.jl +++ b/src/abstractdataframe/io.jl @@ -47,15 +47,8 @@ Base.show(io::IO, mime::MIME"text/csv", df::AbstractDataFrame) = printtable(io, df, header = true, separator = ',') Base.show(io::IO, mime::MIME"text/tab-separated-values", df::AbstractDataFrame) = printtable(io, df, header = true, separator = '\t') -Base.show(io::IO, mime::MIME"text/plain", df::AbstractDataFrame; - allrows::Bool = !get(io, :limit, false), - allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), - rowlabel::Symbol = :Row, - summary::Bool = true, - eltypes::Bool = true) = - show(io, df, allrows=allrows, allcols=allcols, - splitcols=splitcols, rowlabel=rowlabel, summary=summary, eltypes=eltypes) +Base.show(io::IO, mime::MIME"text/plain", df::AbstractDataFrame; kwargs...) = + show(io, df; kwargs...) ############################################################################## # diff --git a/src/abstractdataframe/iteration.jl b/src/abstractdataframe/iteration.jl index 4e6b0c6ec3..a3d089adb2 100644 --- a/src/abstractdataframe/iteration.jl +++ b/src/abstractdataframe/iteration.jl @@ -249,74 +249,76 @@ Base.names(itr::Union{DataFrameRows, DataFrameColumns}, cols) = names(parent(itr function Base.show(io::IO, dfrs::DataFrameRows; allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) + truncate::Int = 32, + kwargs...) df = parent(dfrs) - summary && print(io, "$(nrow(df))×$(ncol(df)) DataFrameRows") - _show(io, df, allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=false, eltypes=eltypes, truncstring=truncate) + title = summary ? "$(nrow(df))×$(ncol(df)) DataFrameRows" : "" + _show(io, df; allrows=allrows, allcols=allcols, rowlabel=rowlabel, + summary=false, eltypes=eltypes, truncate=truncate, title=title, + kwargs...) end Base.show(io::IO, mime::MIME"text/plain", dfrs::DataFrameRows; allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) = - show(io, dfrs, allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=summary, eltypes=eltypes, truncate=truncate) + truncate::Int = 32, + kwargs...) = + show(io, dfrs; allrows=allrows, allcols=allcols, rowlabel=rowlabel, + summary=summary, eltypes=eltypes, truncate=truncate, kwargs...) Base.show(dfrs::DataFrameRows; allrows::Bool = !get(stdout, :limit, true), allcols::Bool = !get(stdout, :limit, true), - splitcols = get(stdout, :limit, true), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) = - show(stdout, dfrs, allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=summary, eltypes=eltypes, truncate=truncate) + truncate::Int = 32, + kwargs...) = + show(stdout, dfrs; allrows=allrows, allcols=allcols, rowlabel=rowlabel, + summary=summary, eltypes=eltypes, truncate=truncate, kwargs...) function Base.show(io::IO, dfcs::DataFrameColumns; allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) + truncate::Int = 32, + kwargs...) df = parent(dfcs) - summary && print(io, "$(nrow(df))×$(ncol(df)) DataFrameColumns") - _show(io, parent(dfcs), allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=false, eltypes=eltypes, truncstring=truncate) + title = summary ? "$(nrow(df))×$(ncol(df)) DataFrameColumns" : "" + _show(io, parent(dfcs); allrows=allrows, allcols=allcols, rowlabel=rowlabel, + summary=false, eltypes=eltypes, truncate=truncate, title=title, + kwargs...) end Base.show(io::IO, mime::MIME"text/plain", dfcs::DataFrameColumns; allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) = - show(io, dfcs, allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=summary, eltypes=eltypes, truncate=truncate) + truncate::Int = 32, + kwargs...) = + show(io, dfcs; allrows=allrows, allcols=allcols, rowlabel=rowlabel, + summary=summary, eltypes=eltypes, truncate=truncate, kwargs...) Base.show(dfcs::DataFrameColumns; allrows::Bool = !get(stdout, :limit, true), allcols::Bool = !get(stdout, :limit, true), - splitcols = get(stdout, :limit, true), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) = - show(stdout, dfcs, allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=summary, eltypes=eltypes, truncate=truncate) + truncate::Int = 32, + kwargs...) = + show(stdout, dfcs; allrows=allrows, allcols=allcols, rowlabel=rowlabel, + summary=summary, eltypes=eltypes, truncate=truncate, kwargs...) """ mapcols(f::Union{Function,Type}, df::AbstractDataFrame) diff --git a/src/abstractdataframe/prettytables.jl b/src/abstractdataframe/prettytables.jl new file mode 100644 index 0000000000..1e9024fbc6 --- /dev/null +++ b/src/abstractdataframe/prettytables.jl @@ -0,0 +1,92 @@ +############################################################################## +## +## Functions related to the interface with PrettyTables.jl. +## +############################################################################## + +# Default DataFrames highlighter for text backend. +# +# This highlighter changes the text color to gray in cells with `nothing`, +# `missing`, `#undef`, and types related to DataFrames.jl. +function _pretty_tables_highlighter_func(data, i::Integer, j::Integer) + try + cell = data[i, j] + return ismissing(cell) || + cell === nothing || + cell isa Union{AbstractDataFrame, GroupedDataFrame, + DataFrameRow, DataFrameRows, + DataFrameColumns} + catch e + if isa(e, UndefRefError) + return true + else + rethrow(e) + end + end +end + +const _PRETTY_TABLES_HIGHLIGHTER = Highlighter(_pretty_tables_highlighter_func, + Crayon(foreground = :dark_gray)) + +# Default DataFrames formatter for text backend. +# +# This formatter changes how the following types are presented when rendering +# the data frame: +# - missing; +# - nothing; +# - Cells with types related to DataFrames.jl. + +function _pretty_tables_general_formatter(v, i::Integer, j::Integer) + if typeof(v) <: Union{AbstractDataFrame, GroupedDataFrame, DataFrameRow, + DataFrameRows, DataFrameColumns} + + # Here, we must not use `print` or `show`. Otherwise, we will call + # `_pretty_table` to render the current table leading to a stack + # overflow. + return sprint(summary, v) + elseif ismissing(v) + return "missing" + elseif v === nothing + return "" + else + return v + end +end + +# Formatter to align the floating points as in Julia array printing. +# +# - `float_cols` contains the IDs of the columns that must be formatted. +# - `indices` is a vector of vectors containing the indices of each elements +# in the data frame. +# - `padding` is a vector of vectors containing the padding of each element for +# each row. +# - `compact_printing` must be a boolean indicating if we should enable the +# `:compact` option of `io` when converting the number to string. + +function _pretty_tables_float_formatter(v, i::Integer, j::Integer, + float_cols::Vector{Int}, + indices::Vector{Vector{Int}}, + padding::Vector{Vector{Int}}, + compact_printing::Bool) + isempty(float_cols) && return v + + # We apply this formatting only to the columns that contains only floats. + ind_col = findfirst(==(j), float_cols) + + if ind_col !== nothing + ind_row = findfirst(==(i), indices[ind_col]) + + if ind_row !== nothing + pad = padding[ind_col][ind_row] + + # Return the formatted number. + str = sprint(print, v, context = :compact => compact_printing) + return " "^pad * str + end + end + + # The formatter is applied to all tables' cells. Hence, we must return the + # input value `v` unchanged if this cell is not part of a column that has + # floating point numbers. + return v +end diff --git a/src/abstractdataframe/show.jl b/src/abstractdataframe/show.jl index ccca7f9bdc..1808d86783 100644 --- a/src/abstractdataframe/show.jl +++ b/src/abstractdataframe/show.jl @@ -573,42 +573,195 @@ function _show(io::IO, df::AbstractDataFrame; allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - rowid=nothing, - truncstring::Int) + rowid = nothing, + truncate::Int = 32, + kwargs...) + _check_consistency(df) - # we will pass around this buffer to avoid its reallocation in ourstrwidth - buffer = IOBuffer(Vector{UInt8}(undef, 80), read=true, write=true) + aux = names(df) + names_len = textwidth.(aux) + maxwidth = max.(9, names_len) + names_mat = permutedims(aux) + types = eltype.(eachcol(df)) + + # NOTE: If we reuse `types` here, the time to print the first table is 2x more. + # This should be something related to type inference. + types_str = permutedims(compacttype.(eltype.(eachcol(df)), maxwidth)) + + if allcols && allrows + crop = :none + elseif allcols + crop = :vertical + elseif allrows + crop = :horizontal + else + crop = :both + end - nrows = size(df, 1) - if rowid !== nothing - if size(df, 2) == 0 - rowid = nothing - elseif nrows != 1 - throw(ArgumentError("rowid may be passed only with a single row data frame")) + compact_printing::Bool = get(io, :compact, true) + + num_rows, num_cols = size(df) + + # By default, we align the columns to the left unless they are numbers, + # which is checked in the following. + alignment = fill(:l, num_cols) + + # This vector stores the column indices that are only floats. In this case, + # the printed numbers will be aligned on the decimal point. + float_cols = Int[] + + # These vectors contain the number of the row and the padding that must be + # applied so that the float number is aligned with on the decimal point + indices = Vector{Int}[] + padding = Vector{Int}[] + + # If the screen is limited, we do not need to process all the numbers. + dsize = displaysize(io) + + if !allcols + # Given the spacing, there is no way to fit more than W/9 rows of + # floating numbers in the screen, where W is the display width. + Δc = clamp(div(dsize[2], 9), 0, num_cols) + else + Δc = num_cols + end + + if !allrows + # Get the maximum number of lines that we can display given the screen size. + Δr = clamp(dsize[1] - 4, 0, num_rows) + else + Δr = num_rows + end + + Δr_lim = cld(Δr, 2) + + # Columns composed of numbers are printed aligned to the left. + for i = 1:Δc + type_i = nonmissingtype(types[i]) + + if type_i <: AbstractFloat + alignment[i] = :r + push!(float_cols, i) + elseif type_i <: Number + alignment[i] = :r end end - dsize = displaysize(io) - availableheight = dsize[1] - 7 - nrowssubset = fld(availableheight, 2) - bound = min(nrowssubset - 1, nrows) - if allrows || nrows <= availableheight - rowindices1 = 1:nrows - rowindices2 = 1:0 + + # Check if the quantity of data to be printed allows the alignment of + # floats. + num_float_cols = length(float_cols) + + if Δr*num_float_cols ≤ 200_000 + for i in float_cols + # Analyze the order of the number to compute the maximum padding + # that must be applied to align the numbers at the decimal + # point. + + max_pad_i = 0 + order_i = zeros(Δr) + indices_i = zeros(Δr) + + col = df[!, i] + + for k = 1:Δr + # We need to process the top and bottom of the table because + # we are cropping in the middle. + + kr = k ≤ Δr_lim ? k : num_rows - (k - Δr_lim) + 1 + + v = col[kr] + + order_v = 0 + + if v isa Number + abs_v = abs(v) + log_v = (v isa Union{Real, Complex} && !isinf(v) && !isnan(v) && abs_v > 1) ? + floor(Int, log10(abs_v))::Int : 0 + + # If the order is higher than 5, then we print using + # scientific notation. + order_v = log_v > 5 ? 0 : floor(Int, log_v) + + # If the number is negative, we need to add an additional + # padding to print the sign. + v < 0 && (order_v += 1) + end + + order_i[k] = order_v + indices_i[k] = kr + + order_v > max_pad_i && (max_pad_i = order_v) + end + + # The algorithm requires the cells to be left aligned. + alignment[i] = :l + + push!(indices, indices_i) + push!(padding, max_pad_i .- order_i) + end else - rowindices1 = 1:bound - rowindices2 = max(bound + 1, nrows - nrowssubset + 1):nrows + empty!(float_cols) end - maxwidths = getmaxwidths(df, io, rowindices1, rowindices2, rowlabel, rowid, - eltypes, buffer, truncstring) - width = getprintedwidth(maxwidths) - showrows(io, df, rowindices1, rowindices2, maxwidths, splitcols, allcols, - rowlabel, summary, eltypes, rowid, buffer, truncstring) - return + + # Create the formatter for floating point columns. + ft_float(v, i, j) = _pretty_tables_float_formatter(v, i, j, float_cols, + indices, padding, + compact_printing) + + # Make sure that `truncate` does not hide the type and the column name. + maximum_columns_width = [truncate == 0 ? 0 : max(truncate + 1, l, textwidth(t)) + for (l, t) in zip(names_len, types_str)] + + # Check if the user wants to display a summary about the DataFrame that is + # being printed. This will be shown using the `title` option of + # `pretty_table`. + title = summary ? Base.summary(df) : "" + + # If `rowid` is not `nothing`, then we are printing a data row. In this + # case, we will add this information using the row name column of + # PrettyTables.jl. Otherwise, we can just use the row number column. + if (rowid === nothing) || (ncol(df) == 0) + show_row_number = true + row_names = nothing + else + nrow(df) != 1 && + throw(ArgumentError("rowid may be passed only with a single row data frame")) + show_row_number = false + row_names = [string(rowid)] + end + + # Print the table with the selected options. + pretty_table(io, df, vcat(names_mat, types_str); + alignment = alignment, + compact_printing = compact_printing, + crop = crop, + crop_num_lines_at_beginning = 2, + ellipsis_line_skip = 3, + formatters = (_pretty_tables_general_formatter, + ft_float), + header_alignment = :l, + hlines = [:header], + highlighters = (_PRETTY_TABLES_HIGHLIGHTER,), + maximum_columns_width = maximum_columns_width, + newline_at_end = false, + nosubheader = !eltypes, + row_name_alignment = :r, + row_name_crayon = Crayon(), + row_name_column_title = string(rowlabel), + row_names = row_names, + row_number_alignment = :r, + row_number_column_title = string(rowlabel), + show_row_number = show_row_number, + title = title, + vcrop_mode = :middle, + vlines = [1], + kwargs...) + + return nothing end """ @@ -616,18 +769,17 @@ end allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), allgroups::Bool = !get(io, :limit, false), - splitcols::Bool = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) + truncate::Int = 32, + kwargs...) Render a data frame to an I/O stream. The specific visual representation chosen depends on the width of the display. If `io` is omitted, the result is printed to `stdout`, -and `allrows`, `allcols` and `allgroups` default to `false` -while `splitcols` defaults to `true`. +and `allrows`, `allcols` and `allgroups` default to `false`. # Arguments - `io::IO`: The I/O stream to which `df` will be printed. @@ -642,16 +794,14 @@ while `splitcols` defaults to `true`. the first and last, when `df` is a `GroupedDataFrame`. By default this is the case only if `io` does not have the `IOContext` property `limit` set. -- `splitcols::Bool`: Whether to split printing in chunks of columns fitting the - screen width rather than printing all columns in the same block. Only applies - if `allcols` is `true`. - By default this is the case only if `io` has the `IOContext` property `limit` set. - `rowlabel::Symbol = :Row`: The label to use for the column containing row numbers. - `summary::Bool = true`: Whether to print a brief string summary of the data frame. - `eltypes::Bool = true`: Whether to print the column types under column names. - `truncate::Int = 32`: the maximal display width the output can use before being truncated (in the `textwidth` sense, excluding `…`). If `truncate` is 0 or less, no truncation is applied. +- `kwargs...`: Any keyword argument supported by the function `pretty_table` of + PrettyTables.jl can be passed here to customize the output. # Examples ```jldoctest @@ -661,34 +811,34 @@ julia> df = DataFrame(A = 1:3, B = ["x", "y", "z"]); julia> show(df, allcols=true) 3×2 DataFrame -│ Row │ A │ B │ -│ │ Int64 │ String │ -├─────┼───────┼────────┤ -│ 1 │ 1 │ x │ -│ 2 │ 2 │ y │ -│ 3 │ 3 │ z │ + Row │ A B + │ Int64 String +─────┼─────────────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z ``` """ Base.show(io::IO, df::AbstractDataFrame; allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) = - _show(io, df, allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=summary, eltypes=eltypes, truncstring=truncate) + truncate::Int = 32, + kwargs...) = + _show(io, df; allrows=allrows, allcols=allcols, rowlabel=rowlabel, + summary=summary, eltypes=eltypes, truncate=truncate, kwargs...) Base.show(df::AbstractDataFrame; allrows::Bool = !get(stdout, :limit, true), allcols::Bool = !get(stdout, :limit, true), - splitcols = get(stdout, :limit, true), rowlabel::Symbol = :Row, summary::Bool = true, eltypes::Bool = true, - truncate::Int = 32) = - show(stdout, df, - allrows=allrows, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=summary, eltypes=eltypes, truncate=truncate) + truncate::Int = 32, + kwargs...) = + show(stdout, df; + allrows=allrows, allcols=allcols, rowlabel=rowlabel, summary=summary, + eltypes=eltypes, truncate=truncate, kwargs...) diff --git a/src/dataframerow/show.jl b/src/dataframerow/show.jl index a4b2016a83..e69d7ff5aa 100644 --- a/src/dataframerow/show.jl +++ b/src/dataframerow/show.jl @@ -1,29 +1,29 @@ function Base.show(io::IO, dfr::DataFrameRow; allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, eltypes::Bool = true, - truncate::Int = 32) + truncate::Int = 32, + kwargs...) r, c = parentindices(dfr) - print(io, "DataFrameRow") - _show(io, view(parent(dfr), [r], c), allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, summary=false, rowid=r, eltypes=eltypes, truncstring=truncate) + _show(io, view(parent(dfr), [r], c); allcols=allcols, rowlabel=rowlabel, + summary=false, rowid=r, eltypes=eltypes, truncate=truncate, + title="DataFrameRow", kwargs...) end Base.show(io::IO, mime::MIME"text/plain", dfr::DataFrameRow; allcols::Bool = !get(io, :limit, false), - splitcols = get(io, :limit, false), rowlabel::Symbol = :Row, eltypes::Bool = true, - truncate::Int = 32) = - show(io, dfr, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, eltypes=eltypes, truncate=truncate) + truncate::Int = 32, + kwargs...) = + show(io, dfr; allcols=allcols, rowlabel=rowlabel, eltypes=eltypes, + truncate=truncate, kwargs...) Base.show(dfr::DataFrameRow; allcols::Bool = !get(stdout, :limit, true), - splitcols = get(stdout, :limit, true), rowlabel::Symbol = :Row, eltypes::Bool = true, - truncate::Int = 32) = - show(stdout, dfr, allcols=allcols, splitcols=splitcols, - rowlabel=rowlabel, eltypes=eltypes, truncate=truncate) + truncate::Int = 32, + kwargs...) = + show(stdout, dfr; allcols=allcols, rowlabel=rowlabel, eltypes=eltypes, + truncate=truncate, kwargs...) diff --git a/src/groupeddataframe/show.jl b/src/groupeddataframe/show.jl index 37948d957c..7a54c371bf 100644 --- a/src/groupeddataframe/show.jl +++ b/src/groupeddataframe/show.jl @@ -10,10 +10,10 @@ function Base.show(io::IO, gd::GroupedDataFrame; allgroups::Bool = !get(io, :limit, false), allrows::Bool = !get(io, :limit, false), allcols::Bool = !get(io, :limit, false), - splitcols::Bool = get(io, :limit, false), rowlabel::Symbol = :Row, summary::Bool = true, - truncate::Int = 32) + truncate::Int = 32, + kwargs...) N = length(gd) summary && Base.summary(io, gd) @@ -28,9 +28,11 @@ function Base.show(io::IO, gd::GroupedDataFrame; print(io, "\nGroup $i ($nrows $rows): ") join(io, identified_groups, ", ") + println(io) - show(io, gd[i], summary=false, - allrows=allrows, allcols=allcols, rowlabel=rowlabel, truncate=truncate) + show(io, gd[i]; summary=false, + allrows=allrows, allcols=allcols, rowlabel=rowlabel, + truncate=truncate, kwargs...) end else if N > 0 @@ -42,9 +44,11 @@ function Base.show(io::IO, gd::GroupedDataFrame; print(io, "\nFirst Group ($nrows $rows): ") join(io, identified_groups, ", ") + println(io) - show(io, gd[1], summary=false, - allrows=allrows, allcols=allcols, rowlabel=rowlabel, truncate=truncate) + show(io, gd[1]; summary=false, + allrows=allrows, allcols=allcols, rowlabel=rowlabel, + truncate=truncate, kwargs...) end if N > 1 nrows = size(gd[N], 1) @@ -55,9 +59,11 @@ function Base.show(io::IO, gd::GroupedDataFrame; print(io, "\n⋮") print(io, "\nLast Group ($nrows $rows): ") join(io, identified_groups, ", ") + println(io) - show(io, gd[N], summary=false, - allrows=allrows, allcols=allcols, rowlabel=rowlabel, truncate=truncate) + show(io, gd[N]; summary=false, + allrows=allrows, allcols=allcols, rowlabel=rowlabel, + truncate=truncate, kwargs...) end end end @@ -66,11 +72,12 @@ function Base.show(df::GroupedDataFrame; allrows::Bool = !get(stdout, :limit, true), allcols::Bool = !get(stdout, :limit, true), allgroups::Bool = !get(stdout, :limit, true), - splitcols::Bool = get(stdout, :limit, true), rowlabel::Symbol = :Row, summary::Bool = true, - truncate::Int = 32) # -> Nothing - return show(stdout, df, + truncate::Int = 32, + kwargs...) # -> Nothing + return show(stdout, df; allrows=allrows, allcols=allcols, allgroups=allgroups, - splitcols=splitcols, rowlabel=rowlabel, summary=summary, truncate=truncate) + rowlabel=rowlabel, summary=summary, truncate=truncate, + kwargs...) end diff --git a/test/dataframerow.jl b/test/dataframerow.jl index 68058de3b6..e8bd8f6afd 100644 --- a/test/dataframerow.jl +++ b/test/dataframerow.jl @@ -422,10 +422,10 @@ end @test sprint(show, DataFrameRow(df, 1, :)) == """ DataFrameRow - │ Row │ a │ b │ - │ │ Nothing │ $(Int) │ - ├─────┼─────────┼───────┤ - │ 1 │ │ 1 │""" + Row │ a b + │ Nothing $(Int) + ─────┼──────────────── + 1 │ 1""" df = DataFrame(a=1:3, b=["a", "b", "c"], c=Int64[1,0,1]) @@ -433,10 +433,10 @@ end @test sprint(show, dfr) == """ DataFrameRow - │ Row │ b │ c │ - │ │ String │ Int64 │ - ├─────┼────────┼───────┤ - │ 2 │ b │ 0 │""" + Row │ b c + │ String Int64 + ─────┼─────────────── + 2 │ b 0""" # Test two-argument show str1, size = capture_stdout() do @@ -478,18 +478,18 @@ end str = String(take!(io)) @test str == """ DataFrameRow - │ Row │ b │ c │ - ├─────┼───┼───┤ - │ 2 │ b │ 0 │""" + Row │ b c + ─────┼────── + 2 │ b 0""" io = IOBuffer() show(io, MIME("text/plain"), dfr, eltypes=false) str = String(take!(io)) @test str == """ DataFrameRow - │ Row │ b │ c │ - ├─────┼───┼───┤ - │ 2 │ b │ 0 │""" + Row │ b c + ─────┼────── + 2 │ b 0""" io = IOBuffer() show(io, MIME("text/html"), dfr, eltypes=false) diff --git a/test/grouping.jl b/test/grouping.jl index ef7de6fb7a..463b0cc763 100644 --- a/test/grouping.jl +++ b/test/grouping.jl @@ -1200,42 +1200,42 @@ end summary_str = summary(gd) @test summary_str == "$GroupedDataFrame with 4 groups based on key: A" @test str == """ - $summary_str - First Group (1 row): A = 1 - │ Row │ A │ B │ C │ - │ │ Int64 │ String │ Float32 │ - ├─────┼───────┼────────┼─────────┤ - │ 1 │ 1 │ x" │ 1.0 │ - ⋮ - Last Group (1 row): A = 4 - │ Row │ A │ B │ C │ - │ │ Int64 │ String │ Float32 │ - ├─────┼───────┼────────┼─────────┤ - │ 1 │ 4 │ A\\nC │ 4.0 │""" + $summary_str + First Group (1 row): A = 1 + Row │ A B C + │ Int64 String Float32 + ─────┼──────────────────────── + 1 │ 1 x" 1.0 + ⋮ + Last Group (1 row): A = 4 + Row │ A B C + │ Int64 String Float32 + ─────┼──────────────────────── + 1 │ 4 A\\nC 4.0""" show(io, gd, allgroups=true) str = String(take!(io.io)) @test str == """ - $summary_str - Group 1 (1 row): A = 1 - │ Row │ A │ B │ C │ - │ │ Int64 │ String │ Float32 │ - ├─────┼───────┼────────┼─────────┤ - │ 1 │ 1 │ x\" │ 1.0 │ - Group 2 (1 row): A = 2 - │ Row │ A │ B │ C │ - │ │ Int64 │ String │ Float32 │ - ├─────┼───────┼─────────────┼─────────┤ - │ 1 │ 2 │ ∀ε>0: x+ε>x │ 2.0 │ - Group 3 (1 row): A = 3 - │ Row │ A │ B │ C │ - │ │ Int64 │ String │ Float32 │ - ├─────┼───────┼────────┼─────────┤ - │ 1 │ 3 │ z\$ │ 3.0 │ - Group 4 (1 row): A = 4 - │ Row │ A │ B │ C │ - │ │ Int64 │ String │ Float32 │ - ├─────┼───────┼────────┼─────────┤ - │ 1 │ 4 │ A\\nC │ 4.0 │""" + $summary_str + Group 1 (1 row): A = 1 + Row │ A B C + │ Int64 String Float32 + ─────┼──────────────────────── + 1 │ 1 x\" 1.0 + Group 2 (1 row): A = 2 + Row │ A B C + │ Int64 String Float32 + ─────┼───────────────────────────── + 1 │ 2 ∀ε>0: x+ε>x 2.0 + Group 3 (1 row): A = 3 + Row │ A B C + │ Int64 String Float32 + ─────┼──────────────────────── + 1 │ 3 z\$ 3.0 + Group 4 (1 row): A = 4 + Row │ A B C + │ Int64 String Float32 + ─────┼──────────────────────── + 1 │ 4 A\\nC 4.0""" # Test two-argument show str1, dsize = capture_stdout() do @@ -1290,10 +1290,10 @@ end @test sprint(show, gd) === """ $summary_str Group 1 (1 row): a = :&, b = "&" - │ Row │ a │ b │ - │ │ Symbol │ String │ - ├─────┼────────┼────────┤ - │ 1 │ & │ & │""" + Row │ a b + │ Symbol String + ─────┼──────────────── + 1 │ & &""" @test sprint(show, "text/html", gd) == "

$summary_str

" * @@ -1448,10 +1448,15 @@ end groupby_checked(DataFrame(x2_identity=[1,1,2]), []) @test isequal_typed(DataFrame(gdf), df) - @test sprint(show, groupby_checked(df, [])) == "GroupedDataFrame with 1 group based on key: \n" * - "Group 1 (3 rows): \n│ Row │ x1 │ x2 │ y │\n│ │ Int64 │ Int64 │ Int64 │\n" * - "├─────┼───────┼───────┼───────┤\n│ 1 │ 1 │ 1 │ 1 │\n" * - "│ 2 │ 2 │ 1 │ 2 │\n│ 3 │ 2 │ 2 │ 3 │" + @test sprint(show, groupby_checked(df, [])) == """ + GroupedDataFrame with 1 group based on key: + Group 1 (3 rows): + Row │ x1 x2 y + │ Int64 Int64 Int64 + ─────┼───────────────────── + 1 │ 1 1 1 + 2 │ 2 1 2 + 3 │ 2 2 3""" df = DataFrame(a=[1, 1, 2, 2, 2], b=1:5) gd = groupby_checked(df, :a) diff --git a/test/io.jl b/test/io.jl index 99bf28dc88..0f5f7122c5 100644 --- a/test/io.jl +++ b/test/io.jl @@ -222,19 +222,20 @@ end " * γ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫αγ∞7∫αγ∞8∫αγ∞9∫αγ∞0"), ] ) - @test sprint(show, "text/plain", df) == """ + @test sprint(show, "text/plain", df) == + """ 8×2 DataFrame - │ Row │ A │ B │ - │ │ Int64 │ Markdown.MD │ - ├─────┼───────┼───────────────────────────────────┤ - │ 1 │ 1 │ [DataFrames.jl](http://juliadata… │ - │ 2 │ 4 │ \$\\frac{x^2}{x^2+y^2}\$ │ - │ 3 │ 9 │ # Header │ - │ 4 │ 16 │ This is *very*, **very**, very, … │ - │ 5 │ 25 │ │ - │ 6 │ 36 │ ∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫α… │ - │ 7 │ 49 │ ∫αγ∞1∫αγ∞… │ - │ 8 │ 64 │ ∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6∫α… │""" + Row │ A B + │ Int64 MD… + ─────┼────────────────────────────────────────── + 1 │ 1 DataFrames.jl (http://juliadat… + 2 │ 4 \\frac{x^2}{x^2+y^2} + 3 │ 9 Header\\n ≡≡≡≡≡≡≡≡ + 4 │ 16 This is very, very, very, very… + 5 │ 25 + 6 │ 36 ∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6… + 7 │ 49 ∫αγ∞1∫αγ∞\\n\\n • 2∫αγ∞3∫α… + 8 │ 64 ∫αγ∞1∫αγ∞2∫αγ∞3∫αγ∞4∫αγ∞5∫αγ∞6…""" @test sprint(show, "text/csv", df) == """ @@ -367,70 +368,70 @@ end show(io, MIME("text/plain"), df, eltypes=true) str = String(take!(io)) @test str == """ - 3×2 DataFrame - │ Row │ A │ B │ - │ │ Int32 │ String │ - ├─────┼───────┼────────┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrame + Row │ A B + │ Int32 String + ─────┼─────────────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" io = IOBuffer() show(io, MIME("text/plain"), eachcol(df), eltypes=true) str = String(take!(io)) @test str == """ - 3×2 DataFrameColumns - │ Row │ A │ B │ - │ │ Int32 │ String │ - ├─────┼───────┼────────┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrameColumns + Row │ A B + │ Int32 String + ─────┼─────────────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" io = IOBuffer() show(io, MIME("text/plain"), eachrow(df), eltypes=true) str = String(take!(io)) @test str == """ - 3×2 DataFrameRows - │ Row │ A │ B │ - │ │ Int32 │ String │ - ├─────┼───────┼────────┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrameRows + Row │ A B + │ Int32 String + ─────┼─────────────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" io = IOBuffer() show(io, MIME("text/plain"), df, eltypes=false) str = String(take!(io)) @test str == """ - 3×2 DataFrame - │ Row │ A │ B │ - ├─────┼───┼───┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrame + Row │ A B + ─────┼────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" io = IOBuffer() show(io, MIME("text/plain"), eachcol(df), eltypes=false) str = String(take!(io)) @test str == """ - 3×2 DataFrameColumns - │ Row │ A │ B │ - ├─────┼───┼───┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrameColumns + Row │ A B + ─────┼────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" io = IOBuffer() show(io, MIME("text/plain"), eachrow(df), eltypes=false) str = String(take!(io)) @test str == """ - 3×2 DataFrameRows - │ Row │ A │ B │ - ├─────┼───┼───┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrameRows + Row │ A B + ─────┼────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" io = IOBuffer() show(io, MIME("text/html"), df, eltypes=true) @@ -531,38 +532,36 @@ end @test str == """ 9×2 DataFrame - │ Row │ A │ B │ - │ │ Int64 │ Any │ - ├─────┼───────┼───────────────────────────────────┤ - │ 1 │ 1 │ 9×2 DataFrame │ - │ 2 │ 2 │ 2-element DataFrameRow │ - │ 3 │ 3 │ 1×2 SubDataFrame │ - │ 4 │ 4 │ 9-element DataFrameRows │ - │ 5 │ 5 │ 2-element DataFrameColumns │ - │ 6 │ 6 │ GroupedDataFrame with 9 groups b… │ - │ 7 │ 7 │ missing │ - │ 8 │ 8 │ │ - │ 9 │ 9 │ #undef │""" - + Row │ A B + │ Int64 Any + ─────┼────────────────────────────────────────── + 1 │ 1 9×2 DataFrame + 2 │ 2 2-element DataFrameRow + 3 │ 3 1×2 SubDataFrame + 4 │ 4 9-element DataFrameRows + 5 │ 5 2-element DataFrameColumns + 6 │ 6 GroupedDataFrame with 9 groups b… + 7 │ 7 missing + 8 │ 8 + 9 │ 9 #undef""" io = IOBuffer() show(IOContext(io, :color => true), df) str = String(take!(io)) @test str == """ - 9×2 DataFrame - │ Row │ A │ B │ - │ │ \e[90mInt64\e[39m │ \e[90mAny\e[39m │ - ├─────┼───────┼───────────────────────────────────┤ - │ 1 │ 1 │ \e[90m9×2 DataFrame\e[39m │ - │ 2 │ 2 │ \e[90m2-element DataFrameRow\e[39m │ - │ 3 │ 3 │ \e[90m1×2 SubDataFrame\e[39m │ - │ 4 │ 4 │ \e[90m9-element DataFrameRows\e[39m │ - │ 5 │ 5 │ \e[90m2-element DataFrameColumns\e[39m │ - │ 6 │ 6 │ \e[90mGroupedDataFrame with 9 groups b…\e[39m │ - │ 7 │ 7 │ \e[90mmissing\e[39m │ - │ 8 │ 8 │ │ - │ 9 │ 9 │ \e[90m#undef\e[39m │""" - + \e[1m9×2 DataFrame\e[0m + \e[1m Row \e[0m│\e[1m A \e[0m\e[1m B \e[0m + \e[1m \e[0m│\e[90m Int64 \e[0m\e[90m Any \e[0m + ─────┼────────────────────────────────────────── + 1 │ 1 \e[90m 9×2 DataFrame \e[0m + 2 │ 2 \e[90m 2-element DataFrameRow \e[0m + 3 │ 3 \e[90m 1×2 SubDataFrame \e[0m + 4 │ 4 \e[90m 9-element DataFrameRows \e[0m + 5 │ 5 \e[90m 2-element DataFrameColumns \e[0m + 6 │ 6 \e[90m GroupedDataFrame with 9 groups b… \e[0m + 7 │ 7 \e[90m missing \e[0m + 8 │ 8 \e[90m \e[0m + 9 │ 9 \e[90m #undef \e[0m""" io = IOBuffer() show(io, MIME("text/html"), df) @@ -691,43 +690,43 @@ end show(io, MIME("text/plain"), df) str = String(take!(io)) @test str == """ - 1×1 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼───────────────────────────────────┤ - │ 1 │ 01234567890123456789012345678901… │""" + 1×1 DataFrame + Row │ x + │ String + ─────┼─────────────────────────────────── + 1 │ 01234567890123456789012345678901…""" io = IOBuffer() show(io, df) str = String(take!(io)) @test str == """ - 1×1 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼───────────────────────────────────┤ - │ 1 │ 01234567890123456789012345678901… │""" + 1×1 DataFrame + Row │ x + │ String + ─────┼─────────────────────────────────── + 1 │ 01234567890123456789012345678901…""" # no truncation io = IOBuffer() show(io, df, truncate=0) str = String(take!(io)) @test str == """ - 1×1 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼──────────────────────────────────────────────────────────────────────────────────────────────────────┤ - │ 1 │ 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 │""" + 1×1 DataFrame + Row │ x + │ String + ─────┼────────────────────────────────────────────────────────────────────────────────────────────────────── + 1 │ 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789""" # custom truncation io = IOBuffer() show(io, df, truncate=1) str = String(take!(io)) @test str == """ - 1×1 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼────────┤ - │ 1 │ 0… │""" + 1×1 DataFrame + Row │ x + │ String + ─────┼──────── + 1 │ 01234…""" df = DataFrame(x12345678901234567890 = "0123456789"^10) @@ -735,11 +734,11 @@ end show(io, df, truncate=1, rowlabel=:r12345678901234567890) str = String(take!(io)) @test str == """ - 1×1 DataFrame - │ r12345678901234567890 │ x12345678901234567890 │ - │ │ String │ - ├───────────────────────┼───────────────────────┤ - │ 1 │ 0… │""" + 1×1 DataFrame + r12345678901234567890 │ x12345678901234567890 + │ String + ───────────────────────┼─────────────────────── + 1 │ 01234567890123456789…""" end diff --git a/test/show.jl b/test/show.jl index 94eb6b47bf..999b3e311a 100644 --- a/test/show.jl +++ b/test/show.jl @@ -28,13 +28,13 @@ end refstr = """ 4×4 DataFrame - │ Row │ A │ B │ C │ D │ - │ │ Int64 │ String │ Float32 │ Char │ - ├─────┼───────┼─────────────┼─────────┼──────┤ - │ 1 │ 1 │ x" │ 1.0 │ ' │ - │ 2 │ 2 │ ∀ε>0: x+ε>x │ 2.0 │ ∀ │ - │ 3 │ 3 │ z\$ │ 3.0 │ \$ │ - │ 4 │ 4 │ A\\nC │ 4.0 │ \\n │""" + Row │ A B C D + │ Int64 String Float32 Char + ─────┼─────────────────────────────────── + 1 │ 1 x" 1.0 ' + 2 │ 2 ∀ε>0: x+ε>x 2.0 ∀ + 3 │ 3 z\$ 3.0 \$ + 4 │ 4 A\\nC 4.0 \\n""" for allrows in [true, false], allcols in [true, false] io = IOBuffer() @@ -49,13 +49,13 @@ end df = DataFrame(A = Vector{String}(undef, 3)) @test sprint(show, df) == """ - 3×1 DataFrame - │ Row │ A │ - │ │ String │ - ├─────┼────────┤ - │ 1 │ #undef │ - │ 2 │ #undef │ - │ 3 │ #undef │""" + 3×1 DataFrame + Row │ A + │ String + ─────┼──────── + 1 │ #undef + 2 │ #undef + 3 │ #undef""" end @testset "displaysize test" begin @@ -65,132 +65,97 @@ end show(io, df_big) str = String(take!(io.io)) @test str == """ - 25×5 DataFrame. Omitted printing of 2 columns - │ Row │ x1 │ x2 │ x3 │ - │ │ Int64 │ Int64 │ Int64 │ - ├─────┼──────────┼──────────┼──────────┤ - │ 1 │ 10000001 │ 10000026 │ 10000051 │ - ⋮ - │ 24 │ 10000024 │ 10000049 │ 10000074 │ - │ 25 │ 10000025 │ 10000050 │ 10000075 │""" + 25×5 DataFrame + Row │ x1 x2 x3 x ⋯ + │ Int64 Int64 Int64 I ⋯ + ─────┼────────────────────────────────── + 1 │ 10000001 10000026 10000051 1 ⋯ + ⋮ │ ⋮ ⋮ ⋮ ⋱ + 25 │ 10000025 10000050 10000075 1 + 2 columns and 23 rows omitted""" io = IOContext(IOBuffer(), :displaysize=>(11,40), :limit=>true) show(io, df_big, allcols=true) str = String(take!(io.io)) @test str == """ - 25×5 DataFrame - │ Row │ x1 │ x2 │ x3 │ - │ │ Int64 │ Int64 │ Int64 │ - ├─────┼──────────┼──────────┼──────────┤ - │ 1 │ 10000001 │ 10000026 │ 10000051 │ - ⋮ - │ 24 │ 10000024 │ 10000049 │ 10000074 │ - │ 25 │ 10000025 │ 10000050 │ 10000075 │ - - │ Row │ x4 │ x5 │ - │ │ Int64 │ Int64 │ - ├─────┼──────────┼──────────┤ - │ 1 │ 10000076 │ 10000101 │ - ⋮ - │ 24 │ 10000099 │ 10000124 │ - │ 25 │ 10000100 │ 10000125 │""" + 25×5 DataFrame + Row │ x1 x2 x3 x4 x5 + │ Int64 Int64 Int64 Int64 Int64 + ─────┼────────────────────────────────────────────────── + 1 │ 10000001 10000026 10000051 10000076 10000101 + 2 │ 10000002 10000027 10000052 10000077 10000102 + ⋮ │ ⋮ ⋮ ⋮ ⋮ ⋮ + 25 │ 10000025 10000050 10000075 10000100 10000125 + 22 rows omitted""" io = IOContext(IOBuffer(), :displaysize=>(11,40), :limit=>true) show(io, df_big, allrows=true, allcols=true) str = String(take!(io.io)) @test str == """ - 25×5 DataFrame - │ Row │ x1 │ x2 │ x3 │ - │ │ Int64 │ Int64 │ Int64 │ - ├─────┼──────────┼──────────┼──────────┤ - │ 1 │ 10000001 │ 10000026 │ 10000051 │ - │ 2 │ 10000002 │ 10000027 │ 10000052 │ - │ 3 │ 10000003 │ 10000028 │ 10000053 │ - │ 4 │ 10000004 │ 10000029 │ 10000054 │ - │ 5 │ 10000005 │ 10000030 │ 10000055 │ - │ 6 │ 10000006 │ 10000031 │ 10000056 │ - │ 7 │ 10000007 │ 10000032 │ 10000057 │ - │ 8 │ 10000008 │ 10000033 │ 10000058 │ - │ 9 │ 10000009 │ 10000034 │ 10000059 │ - │ 10 │ 10000010 │ 10000035 │ 10000060 │ - │ 11 │ 10000011 │ 10000036 │ 10000061 │ - │ 12 │ 10000012 │ 10000037 │ 10000062 │ - │ 13 │ 10000013 │ 10000038 │ 10000063 │ - │ 14 │ 10000014 │ 10000039 │ 10000064 │ - │ 15 │ 10000015 │ 10000040 │ 10000065 │ - │ 16 │ 10000016 │ 10000041 │ 10000066 │ - │ 17 │ 10000017 │ 10000042 │ 10000067 │ - │ 18 │ 10000018 │ 10000043 │ 10000068 │ - │ 19 │ 10000019 │ 10000044 │ 10000069 │ - │ 20 │ 10000020 │ 10000045 │ 10000070 │ - │ 21 │ 10000021 │ 10000046 │ 10000071 │ - │ 22 │ 10000022 │ 10000047 │ 10000072 │ - │ 23 │ 10000023 │ 10000048 │ 10000073 │ - │ 24 │ 10000024 │ 10000049 │ 10000074 │ - │ 25 │ 10000025 │ 10000050 │ 10000075 │ - - │ Row │ x4 │ x5 │ - │ │ Int64 │ Int64 │ - ├─────┼──────────┼──────────┤ - │ 1 │ 10000076 │ 10000101 │ - │ 2 │ 10000077 │ 10000102 │ - │ 3 │ 10000078 │ 10000103 │ - │ 4 │ 10000079 │ 10000104 │ - │ 5 │ 10000080 │ 10000105 │ - │ 6 │ 10000081 │ 10000106 │ - │ 7 │ 10000082 │ 10000107 │ - │ 8 │ 10000083 │ 10000108 │ - │ 9 │ 10000084 │ 10000109 │ - │ 10 │ 10000085 │ 10000110 │ - │ 11 │ 10000086 │ 10000111 │ - │ 12 │ 10000087 │ 10000112 │ - │ 13 │ 10000088 │ 10000113 │ - │ 14 │ 10000089 │ 10000114 │ - │ 15 │ 10000090 │ 10000115 │ - │ 16 │ 10000091 │ 10000116 │ - │ 17 │ 10000092 │ 10000117 │ - │ 18 │ 10000093 │ 10000118 │ - │ 19 │ 10000094 │ 10000119 │ - │ 20 │ 10000095 │ 10000120 │ - │ 21 │ 10000096 │ 10000121 │ - │ 22 │ 10000097 │ 10000122 │ - │ 23 │ 10000098 │ 10000123 │ - │ 24 │ 10000099 │ 10000124 │ - │ 25 │ 10000100 │ 10000125 │""" + 25×5 DataFrame + Row │ x1 x2 x3 x4 x5 + │ Int64 Int64 Int64 Int64 Int64 + ─────┼────────────────────────────────────────────────── + 1 │ 10000001 10000026 10000051 10000076 10000101 + 2 │ 10000002 10000027 10000052 10000077 10000102 + 3 │ 10000003 10000028 10000053 10000078 10000103 + 4 │ 10000004 10000029 10000054 10000079 10000104 + 5 │ 10000005 10000030 10000055 10000080 10000105 + 6 │ 10000006 10000031 10000056 10000081 10000106 + 7 │ 10000007 10000032 10000057 10000082 10000107 + 8 │ 10000008 10000033 10000058 10000083 10000108 + 9 │ 10000009 10000034 10000059 10000084 10000109 + 10 │ 10000010 10000035 10000060 10000085 10000110 + 11 │ 10000011 10000036 10000061 10000086 10000111 + 12 │ 10000012 10000037 10000062 10000087 10000112 + 13 │ 10000013 10000038 10000063 10000088 10000113 + 14 │ 10000014 10000039 10000064 10000089 10000114 + 15 │ 10000015 10000040 10000065 10000090 10000115 + 16 │ 10000016 10000041 10000066 10000091 10000116 + 17 │ 10000017 10000042 10000067 10000092 10000117 + 18 │ 10000018 10000043 10000068 10000093 10000118 + 19 │ 10000019 10000044 10000069 10000094 10000119 + 20 │ 10000020 10000045 10000070 10000095 10000120 + 21 │ 10000021 10000046 10000071 10000096 10000121 + 22 │ 10000022 10000047 10000072 10000097 10000122 + 23 │ 10000023 10000048 10000073 10000098 10000123 + 24 │ 10000024 10000049 10000074 10000099 10000124 + 25 │ 10000025 10000050 10000075 10000100 10000125""" io = IOContext(IOBuffer(), :displaysize=>(11,40), :limit=>true) show(io, df_big, allrows=true, allcols=false) str = String(take!(io.io)) @test str == """ - 25×5 DataFrame. Omitted printing of 2 columns - │ Row │ x1 │ x2 │ x3 │ - │ │ Int64 │ Int64 │ Int64 │ - ├─────┼──────────┼──────────┼──────────┤ - │ 1 │ 10000001 │ 10000026 │ 10000051 │ - │ 2 │ 10000002 │ 10000027 │ 10000052 │ - │ 3 │ 10000003 │ 10000028 │ 10000053 │ - │ 4 │ 10000004 │ 10000029 │ 10000054 │ - │ 5 │ 10000005 │ 10000030 │ 10000055 │ - │ 6 │ 10000006 │ 10000031 │ 10000056 │ - │ 7 │ 10000007 │ 10000032 │ 10000057 │ - │ 8 │ 10000008 │ 10000033 │ 10000058 │ - │ 9 │ 10000009 │ 10000034 │ 10000059 │ - │ 10 │ 10000010 │ 10000035 │ 10000060 │ - │ 11 │ 10000011 │ 10000036 │ 10000061 │ - │ 12 │ 10000012 │ 10000037 │ 10000062 │ - │ 13 │ 10000013 │ 10000038 │ 10000063 │ - │ 14 │ 10000014 │ 10000039 │ 10000064 │ - │ 15 │ 10000015 │ 10000040 │ 10000065 │ - │ 16 │ 10000016 │ 10000041 │ 10000066 │ - │ 17 │ 10000017 │ 10000042 │ 10000067 │ - │ 18 │ 10000018 │ 10000043 │ 10000068 │ - │ 19 │ 10000019 │ 10000044 │ 10000069 │ - │ 20 │ 10000020 │ 10000045 │ 10000070 │ - │ 21 │ 10000021 │ 10000046 │ 10000071 │ - │ 22 │ 10000022 │ 10000047 │ 10000072 │ - │ 23 │ 10000023 │ 10000048 │ 10000073 │ - │ 24 │ 10000024 │ 10000049 │ 10000074 │ - │ 25 │ 10000025 │ 10000050 │ 10000075 │""" + 25×5 DataFrame + Row │ x1 x2 x3 x ⋯ + │ Int64 Int64 Int64 I ⋯ + ─────┼────────────────────────────────── + 1 │ 10000001 10000026 10000051 1 ⋯ + 2 │ 10000002 10000027 10000052 1 + 3 │ 10000003 10000028 10000053 1 + 4 │ 10000004 10000029 10000054 1 + 5 │ 10000005 10000030 10000055 1 ⋯ + 6 │ 10000006 10000031 10000056 1 + 7 │ 10000007 10000032 10000057 1 + 8 │ 10000008 10000033 10000058 1 + 9 │ 10000009 10000034 10000059 1 ⋯ + 10 │ 10000010 10000035 10000060 1 + 11 │ 10000011 10000036 10000061 1 + 12 │ 10000012 10000037 10000062 1 + 13 │ 10000013 10000038 10000063 1 ⋯ + 14 │ 10000014 10000039 10000064 1 + 15 │ 10000015 10000040 10000065 1 + 16 │ 10000016 10000041 10000066 1 + 17 │ 10000017 10000042 10000067 1 ⋯ + 18 │ 10000018 10000043 10000068 1 + 19 │ 10000019 10000044 10000069 1 + 20 │ 10000020 10000045 10000070 1 + 21 │ 10000021 10000046 10000071 1 ⋯ + 22 │ 10000022 10000047 10000072 1 + 23 │ 10000023 10000048 10000073 1 + 24 │ 10000024 10000049 10000074 1 + 25 │ 10000025 10000050 10000075 1 ⋯ + 2 columns omitted""" end @testset "IOContext parameters test" begin @@ -223,12 +188,12 @@ end show(io, subdf, allrows=true, allcols=false) str = String(take!(io)) @test str == """ - 2×3 SubDataFrame - │ Row │ A │ B │ C │ - │ │ Int64 │ String │ Float32 │ - ├─────┼───────┼─────────────┼─────────┤ - │ 1 │ 2 │ ∀ε>0: x+ε>x │ 2.0 │ - │ 2 │ 3 │ z\$ │ 3.0 │""" + 2×3 SubDataFrame + Row │ A B C + │ Int64 String Float32 + ─────┼───────────────────────────── + 1 │ 2 ∀ε>0: x+ε>x 2.0 + 2 │ 3 z\$ 3.0""" show(io, subdf, allrows=true) show(io, subdf, allcols=true) show(io, subdf, allcols=true, allrows=true) @@ -246,107 +211,107 @@ end @testset "Test colors and non-standard values: missing and nothing" begin df = DataFrame(Fish = ["Suzy", "Amir"], Mass = [1.5, missing]) @test sprint(show, df, context=:color=>true) == """ - 2×2 DataFrame - │ Row │ Fish │ Mass │ - │ │ \e[90mString\e[39m │ \e[90mFloat64?\e[39m │ - ├─────┼────────┼──────────┤ - │ 1 │ Suzy │ 1.5 │ - │ 2 │ Amir │ \e[90mmissing\e[39m │""" + \e[1m2×2 DataFrame\e[0m + \e[1m Row \e[0m│\e[1m Fish \e[0m\e[1m Mass \e[0m + \e[1m \e[0m│\e[90m String \e[0m\e[90m Float64? \e[0m + ─────┼────────────────── + 1 │ Suzy 1.5 + 2 │ Amir \e[90m missing \e[0m""" df = DataFrame(A = [:Symbol, missing, :missing], B = [missing, "String", "missing"], C = [:missing, "missing", missing]) @test sprint(show, df, context=:color=>true) == """ - 3×3 DataFrame - │ Row │ A │ B │ C │ - │ │ \e[90mSymbol?\e[39m │ \e[90mString?\e[39m │ \e[90mAny\e[39m │ - ├─────┼─────────┼─────────┼─────────┤ - │ 1 │ Symbol │ \e[90mmissing\e[39m │ missing │ - │ 2 │ \e[90mmissing\e[39m │ String │ missing │ - │ 3 │ missing │ missing │ \e[90mmissing\e[39m │""" + \e[1m3×3 DataFrame\e[0m + \e[1m Row \e[0m│\e[1m A \e[0m\e[1m B \e[0m\e[1m C \e[0m + \e[1m \e[0m│\e[90m Symbol? \e[0m\e[90m String? \e[0m\e[90m Any \e[0m + ─────┼─────────────────────────── + 1 │ Symbol \e[90m missing \e[0m missing + 2 │\e[90m missing \e[0m String missing + 3 │ missing missing \e[90m missing \e[0m""" df_nothing = DataFrame(A = [1.0, 2.0, 3.0], B = ["g", "g", nothing]) @test sprint(show, df_nothing) == """ - 3×2 DataFrame - │ Row │ A │ B │ - │ │ Float64 │ Union… │ - ├─────┼─────────┼────────┤ - │ 1 │ 1.0 │ g │ - │ 2 │ 2.0 │ g │ - │ 3 │ 3.0 │ │""" + 3×2 DataFrame + Row │ A B + │ Float64 Union… + ─────┼───────────────── + 1 │ 1.0 g + 2 │ 2.0 g + 3 │ 3.0""" end @testset "Test correct width computation" begin df = DataFrame([["a"]], [:x]) @test sprint(show, df) == """ - 1×1 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼────────┤ - │ 1 │ a │""" + 1×1 DataFrame + Row │ x + │ String + ─────┼──────── + 1 │ a""" end @testset "Test showing special types" begin # strings with escapes df = DataFrame(a = ["1\n1", "2\t2", "3\r3", "4\$4", "5\"5", "6\\6"]) @test sprint(show, df) == """ - 6×1 DataFrame - │ Row │ a │ - │ │ String │ - ├─────┼────────┤ - │ 1 │ 1\\n1 │ - │ 2 │ 2\\t2 │ - │ 3 │ 3\\r3 │ - │ 4 │ 4\$4 │ - │ 5 │ 5"5 │ - │ 6 │ 6\\\\6 │""" + 6×1 DataFrame + Row │ a + │ String + ─────┼──────── + 1 │ 1\\n1 + 2 │ 2\\t2 + 3 │ 3\\r3 + 4 │ 4\$4 + 5 │ 5"5 + 6 │ 6\\\\6""" # categorical df = DataFrame(a = categorical([1,2,3]), b = categorical(["a", "b", missing])) @test sprint(show, df) == """ - 3×2 DataFrame - │ Row │ a │ b │ - │ │ Cat… │ Cat…? │ - ├─────┼──────┼─────────┤ - │ 1 │ 1 │ a │ - │ 2 │ 2 │ b │ - │ 3 │ 3 │ missing │""" + 3×2 DataFrame + Row │ a b + │ Cat… Cat…? + ─────┼─────────────── + 1 │ 1 a + 2 │ 2 b + 3 │ 3 missing""" # BigFloat df = DataFrame(a = [big(1.0), missing]) @test sprint(show, df) == """ - 2×1 DataFrame - │ Row │ a │ - │ │ BigFloat? │ - ├─────┼───────────┤ - │ 1 │ 1.0 │ - │ 2 │ missing │""" + 2×1 DataFrame + Row │ a + │ BigFloat? + ─────┼─────────── + 1 │ 1.0 + 2 │ missing""" # date types df = DataFrame(a = Date(2020, 2, 11), b = DateTime(2020, 2, 11, 15), c = Day(1)) @test sprint(show, df) == """ - 1×3 DataFrame - │ Row │ a │ b │ c │ - │ │ Date │ DateTime │ Day │ - ├─────┼────────────┼─────────────────────┼───────┤ - │ 1 │ 2020-02-11 │ 2020-02-11T15:00:00 │ 1 day │""" + 1×3 DataFrame + Row │ a b c + │ Date DateTime Day + ─────┼──────────────────────────────────────── + 1 │ 2020-02-11 2020-02-11T15:00:00 1 day""" # Irrational df = DataFrame(a = π) if VERSION < v"1.2.0-DEV.276" @test sprint(show, df) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ Irrational{:π} │ - ├─────┼────────────────────────┤ - │ 1 │ π = 3.1415926535897... │""" + 1×1 DataFrame + Row │ a + │ Irrational{:π} + ─────┼──────────────────────── + 1 │ π = 3.1415926535897...""" else @test sprint(show, df) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ Irratio… │ - ├─────┼──────────┤ - │ 1 │ π │""" + 1×1 DataFrame + Row │ a + │ Irration… + ─────┼─────────── + 1 │ π""" end end @@ -354,54 +319,52 @@ end df = DataFrame(x = [float(pi)]) @test sprint(show, df) == """ 1×1 DataFrame - │ Row │ x │ - │ │ Float64 │ - ├─────┼─────────┤ - │ 1 │ 3.14159 │""" + Row │ x + │ Float64 + ─────┼───────── + 1 │ 3.14159""" @test sprint(show, df, context=:compact=>false) == """ 1×1 DataFrame - │ Row │ x │ - │ │ Float64 │ - ├─────┼───────────────────┤ - │ 1 │ 3.141592653589793 │""" + Row │ x + │ Float64 + ─────┼─────────────────── + 1 │ 3.141592653589793""" end @testset "Test of DataFrameRows and DataFrameColumns" begin df = DataFrame(x = [float(pi)]) @test sprint(show, eachrow(df)) == """ 1×1 DataFrameRows - │ Row │ x │ - │ │ Float64 │ - ├─────┼─────────┤ - │ 1 │ 3.14159 │""" + Row │ x + │ Float64 + ─────┼───────── + 1 │ 3.14159""" @test sprint((io, x) -> show(io, x, summary=false), eachrow(df)) == """ - - │ Row │ x │ - │ │ Float64 │ - ├─────┼─────────┤ - │ 1 │ 3.14159 │""" + Row │ x + │ Float64 + ─────┼───────── + 1 │ 3.14159""" @test sprint(show, eachcol(df)) == """ 1×1 DataFrameColumns - │ Row │ x │ - │ │ Float64 │ - ├─────┼─────────┤ - │ 1 │ 3.14159 │""" + Row │ x + │ Float64 + ─────┼───────── + 1 │ 3.14159""" @test sprint((io, x) -> show(io, x, summary=false), eachcol(df)) == """ - - │ Row │ x │ - │ │ Float64 │ - ├─────┼─────────┤ - │ 1 │ 3.14159 │""" + Row │ x + │ Float64 + ─────┼───────── + 1 │ 3.14159""" end @testset "Test empty data frame and DataFrameRow" begin df = DataFrame(x = [float(pi)]) - @test sprint(show, df[:, 2:1]) == "0×0 DataFrame\n" - @test sprint(show, @view df[:, 2:1]) == "0×0 SubDataFrame\n" + @test sprint(show, df[:, 2:1]) == "0×0 DataFrame" + @test sprint(show, @view df[:, 2:1]) == "0×0 SubDataFrame" @test sprint(show, df[1, 2:1]) == "DataFrameRow" end @@ -417,46 +380,46 @@ end @testset "wide type name" begin @test sprint(show, DataFrame(a=⛵⛵⛵⛵⛵())) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ ⛵⛵⛵… │ - ├─────┼─────────┤ - │ 1 │ "⛵" │""" + 1×1 DataFrame + Row │ a + │ ⛵⛵⛵⛵… + ─────┼─────────── + 1 │ "⛵\"""" @test sprint(show, DataFrame(a=categorical([Int64(2)^54]))) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ CategoricalValue… │ - ├─────┼───────────────────┤ - │ 1 │ 18014398509481984 │""" + 1×1 DataFrame + Row │ a + │ Cat… + ─────┼─────────────────── + 1 │ 18014398509481984""" @test sprint(show, DataFrame(a=categorical([Int64(2)^53]))) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ Categorical… │ - ├─────┼──────────────────┤ - │ 1 │ 9007199254740992 │""" + 1×1 DataFrame + Row │ a + │ Cat… + ─────┼────────────────── + 1 │ 9007199254740992""" @test sprint(show, DataFrame(a=categorical([Int64(2)^37]))) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ Categorical… │ - ├─────┼──────────────┤ - │ 1 │ 137438953472 │""" + 1×1 DataFrame + Row │ a + │ Cat… + ─────┼────────────── + 1 │ 137438953472""" @test sprint(show, DataFrame(a=categorical([Int64(2)^36]))) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ Cat… │ - ├─────┼─────────────┤ - │ 1 │ 68719476736 │""" + 1×1 DataFrame + Row │ a + │ Cat… + ─────┼───────────── + 1 │ 68719476736""" @test sprint(show, DataFrame(a=Union{Function,Missing}[missing])) == """ - 1×1 DataFrame - │ Row │ a │ - │ │ Function? │ - ├─────┼───────────┤ - │ 1 │ missing │""" + 1×1 DataFrame + Row │ a + │ Function? + ─────┼─────────── + 1 │ missing""" end @testset "wide type name" begin @@ -466,24 +429,24 @@ end show(io, df, eltypes=true) str = String(take!(io)) @test str == """ - 3×2 DataFrame - │ Row │ A │ B │ - │ │ Int32 │ String │ - ├─────┼───────┼────────┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrame + Row │ A B + │ Int32 String + ─────┼─────────────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" io = IOBuffer() show(io, df, eltypes=false) str = String(take!(io)) @test str == """ - 3×2 DataFrame - │ Row │ A │ B │ - ├─────┼───┼───┤ - │ 1 │ 1 │ x │ - │ 2 │ 2 │ y │ - │ 3 │ 3 │ z │""" + 3×2 DataFrame + Row │ A B + ─────┼────── + 1 │ 1 x + 2 │ 2 y + 3 │ 3 z""" end @testset "UnionAll" begin @@ -493,11 +456,11 @@ end show(io, df) str = String(take!(io)) @test str == """ - 1×1 DataFrame - │ Row │ x │ - │ │ Abstrac… │ - ├─────┼──────────┤ - │ 1 │ 1:2 │""" + 1×1 DataFrame + Row │ x + │ Abstract… + ─────┼─────────── + 1 │ 1:2""" end @testset "wide output and column trimming" begin @@ -506,43 +469,64 @@ end show(io, df) str = String(take!(io)) @test str == """ - 1×1 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼───────────────────────────────────┤ - │ 1 │ 01234567890123456789012345678901… │""" + 1×1 DataFrame + Row │ x + │ String + ─────┼─────────────────────────────────── + 1 │ 01234567890123456789012345678901…""" io = IOContext(IOBuffer(), :displaysize=>(10,10), :limit=>true) show(io, df) str = String(take!(io.io)) - @test str === "1×1 DataFrame. Omitted printing of all columns as they do not fit the display size" - - df = DataFrame(x = "0123456789"^4, y = "0123456789"^4) - io = IOContext(IOBuffer(), :displaysize=>(10,10), :limit=>true) - show(io, df, splitcols=true, allcols=true) - str = String(take!(io.io)) @test str === """ - 1×2 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼───────────────────────────────────┤ - │ 1 │ 01234567890123456789012345678901… │ - - │ Row │ y │ - │ │ String │ - ├─────┼───────────────────────────────────┤ - │ 1 │ 01234567890123456789012345678901… │""" + 1×1 DataF… + Row │ x ⋯ + │ S ⋯ + ─────┼──── + 1 │ 0 ⋯ + 1 column omitted""" df = DataFrame(x = "😄"^20) - io = IOBuffer() + io = IOBuffer() show(io, df) str = String(take!(io)) @test str === """ - 1×1 DataFrame - │ Row │ x │ - │ │ String │ - ├─────┼───────────────────────────────────┤ - │ 1 │ 😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄… │""" + 1×1 DataFrame + Row │ x + │ String + ─────┼─────────────────────────────────── + 1 │ 😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄😄…""" +end + +@testset "Floating point alignment" begin + df = DataFrame(a = [i == 2 ? missing : 10^i for i = -7:1.:7], + b = 1:1:15, + c = [i % 2 == 0 for i = 1:15], + d = [i == 2 ? "test" : 10^i for i = -7:1.:7]) + + io = IOBuffer() + show(io, df) + str = String(take!(io)) + @test str == """ + 15×4 DataFrame + Row │ a b c d + │ Float64? Int64 Bool Any + ─────┼────────────────────────────────────── + 1 │ 1.0e-7 1 false 1.0e-7 + 2 │ 1.0e-6 2 true 1.0e-6 + 3 │ 1.0e-5 3 false 1.0e-5 + 4 │ 0.0001 4 true 0.0001 + 5 │ 0.001 5 false 0.001 + 6 │ 0.01 6 true 0.01 + 7 │ 0.1 7 false 0.1 + 8 │ 1.0 8 true 1.0 + 9 │ 10.0 9 false 10.0 + 10 │ missing 10 true test + 11 │ 1000.0 11 false 1000.0 + 12 │ 10000.0 12 true 10000.0 + 13 │ 100000.0 13 false 100000.0 + 14 │ 1.0e6 14 true 1.0e6 + 15 │ 1.0e7 15 false 1.0e7""" end end # module