Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add displaycoltypes to showrows & show for dataframes #2142

Merged
merged 18 commits into from
Mar 12, 2020
Merged
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
68 changes: 38 additions & 30 deletions src/abstractdataframe/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ julia> show(stdout, MIME("text/csv"), DataFrame(A = 1:3, B = ["x", "y", "z"]))
```
"""
Base.show(io::IO, mime::MIME, df::AbstractDataFrame)
Base.show(io::IO, mime::MIME"text/html", df::AbstractDataFrame; summary::Bool=true) =
_show(io, mime, df, summary=summary)
Base.show(io::IO, mime::MIME"text/latex", df::AbstractDataFrame) =
_show(io, mime, df)
Base.show(io::IO, mime::MIME"text/html", df::AbstractDataFrame; summary::Bool=true, eltypes::Bool=true) =
_show(io, mime, df, summary=summary, eltypes=eltypes)
Base.show(io::IO, mime::MIME"text/latex", df::AbstractDataFrame; eltypes::Bool=true) =
_show(io, mime, df, eltypes=eltypes)
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) =
Expand All @@ -50,9 +50,10 @@ Base.show(io::IO, mime::MIME"text/plain", df::AbstractDataFrame;
allcols::Bool = !get(io, :limit, false),
splitcols = get(io, :limit, false),
rowlabel::Symbol = :Row,
summary::Bool = true) =
summary::Bool = true,
eltypes::Bool = true) =
show(io, df, allrows=allrows, allcols=allcols,
splitcols=splitcols, rowlabel=rowlabel, summary=summary)
splitcols=splitcols, rowlabel=rowlabel, summary=summary, eltypes=eltypes)

##############################################################################
#
Expand All @@ -77,7 +78,7 @@ function html_escape(cell::AbstractString)
end

function _show(io::IO, ::MIME"text/html", df::AbstractDataFrame;
summary::Bool=true, rowid::Union{Int,Nothing}=nothing)
summary::Bool=true, rowid::Union{Int,Nothing}=nothing, eltypes::Bool=true)
_check_consistency(df)
if rowid !== nothing
if size(df, 2) == 0
Expand All @@ -104,13 +105,15 @@ function _show(io::IO, ::MIME"text/html", df::AbstractDataFrame;
write(io, "<th>$(html_escape(String(column_name)))</th>")
end
write(io, "</tr>")
write(io, "<tr>")
write(io, "<th></th>")
for j in 1:mxcol
s = html_escape(compacttype(eltype(df[!, j])))
write(io, "<th>$s</th>")
if eltypes
write(io, "<tr>")
write(io, "<th></th>")
for j in 1:mxcol
s = html_escape(compacttype(eltype(df[!, j])))
write(io, "<th>$s</th>")
end
write(io, "</tr>")
end
write(io, "</tr>")
write(io, "</thead>")
write(io, "<tbody>")
if summary
Expand Down Expand Up @@ -150,25 +153,25 @@ function _show(io::IO, ::MIME"text/html", df::AbstractDataFrame;
write(io, "</table>")
end

function Base.show(io::IO, mime::MIME"text/html", dfr::DataFrameRow; summary::Bool=true)
function Base.show(io::IO, mime::MIME"text/html", dfr::DataFrameRow; summary::Bool=true, eltypes::Bool=true)
r, c = parentindices(dfr)
summary && write(io, "<p>DataFrameRow ($(length(dfr)) columns)</p>")
_show(io, mime, view(parent(dfr), [r], c), summary=false, rowid=r)
_show(io, mime, view(parent(dfr), [r], c), summary=false, rowid=r, eltypes=eltypes)
end

function Base.show(io::IO, mime::MIME"text/html", dfrs::DataFrameRows; summary::Bool=true)
function Base.show(io::IO, mime::MIME"text/html", dfrs::DataFrameRows; summary::Bool=true, eltypes::Bool=true)
df = parent(dfrs)
summary && write(io, "<p>$(nrow(df))×$(ncol(df)) DataFrameRows</p>")
_show(io, mime, df, summary=false)
_show(io, mime, df, summary=false, eltypes=eltypes)
end

function Base.show(io::IO, mime::MIME"text/html", dfcs::DataFrameColumns;
summary::Bool=true)
summary::Bool=true, eltypes::Bool=true)
df = parent(dfcs)
if summary
write(io, "<p>$(nrow(df))×$(ncol(df)) DataFrameColumns</p>")
end
_show(io, mime, df, summary=false)
_show(io, mime, df, summary=false, eltypes=eltypes)
end

function Base.show(io::IO, mime::MIME"text/html", gd::GroupedDataFrame)
Expand Down Expand Up @@ -226,7 +229,8 @@ function latex_escape(cell::AbstractString)
replace(cell, ['\\','~','#','$','%','&','_','^','{','}']=>latex_char_escape)
end

function _show(io::IO, ::MIME"text/latex", df::AbstractDataFrame; rowid=nothing)
function _show(io::IO, ::MIME"text/latex", df::AbstractDataFrame;
rowid=nothing, eltypes::Bool=true)
_check_consistency(df)
if rowid !== nothing
if size(df, 2) == 0
Expand Down Expand Up @@ -256,12 +260,14 @@ function _show(io::IO, ::MIME"text/latex", df::AbstractDataFrame; rowid=nothing)
mxcol < size(df, 2) && write(io, " & ")
write(io, "\\\\\n")
write(io, "\t\\hline\n")
write(io, "\t& ")
header = join(map(c -> latex_escape(string(compacttype(c))), eltype.(eachcol(df)[1:mxcol])), " & ")
write(io, header)
mxcol < size(df, 2) && write(io, " & ")
write(io, "\\\\\n")
write(io, "\t\\hline\n")
if eltypes
write(io, "\t& ")
header = join(map(c -> latex_escape(string(compacttype(c))), eltype.(eachcol(df)[1:mxcol])), " & ")
write(io, header)
mxcol < size(df, 2) && write(io, " & ")
write(io, "\\\\\n")
write(io, "\t\\hline\n")
end
for row in 1:mxrow
write(io, "\t")
write(io, @sprintf("%d", rowid === nothing ? row : rowid))
Expand Down Expand Up @@ -290,13 +296,15 @@ function _show(io::IO, ::MIME"text/latex", df::AbstractDataFrame; rowid=nothing)
write(io, "\\end{tabular}\n")
end

function Base.show(io::IO, mime::MIME"text/latex", dfr::DataFrameRow)
function Base.show(io::IO, mime::MIME"text/latex", dfr::DataFrameRow; eltypes::Bool=true)
r, c = parentindices(dfr)
_show(io, mime, view(parent(dfr), [r], c), rowid=r)
_show(io, mime, view(parent(dfr), [r], c), rowid=r, eltypes=eltypes)
end

Base.show(io::IO, mime::MIME"text/latex", dfrs::DataFrameRows) = _show(io, mime, parent(dfrs))
Base.show(io::IO, mime::MIME"text/latex", dfcs::DataFrameColumns) = _show(io, mime, parent(dfcs))
Base.show(io::IO, mime::MIME"text/latex", dfrs::DataFrameRows; eltypes::Bool=true) =
_show(io, mime, parent(dfrs), eltypes=eltypes)
Base.show(io::IO, mime::MIME"text/latex", dfcs::DataFrameColumns; eltypes::Bool=true) =
_show(io, mime, parent(dfcs), eltypes=eltypes)

function Base.show(io::IO, mime::MIME"text/latex", gd::GroupedDataFrame)
N = length(gd)
Expand Down
58 changes: 37 additions & 21 deletions src/abstractdataframe/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@ function getmaxwidths(df::AbstractDataFrame,
rowindices1::AbstractVector{Int},
rowindices2::AbstractVector{Int},
rowlabel::Symbol,
rowid=nothing) # -> Vector{Int}
rowid=nothing,
show_eltype::Bool=true) # -> Vector{Int}
maxwidths = Vector{Int}(undef, size(df, 2) + 1)

undefstrwidth = ourstrwidth(io, Base.undef_ref_str)
Expand All @@ -172,7 +173,11 @@ function getmaxwidths(df::AbstractDataFrame,
maxwidth = max(maxwidth, undefstrwidth)
end
end
maxwidths[j] = max(maxwidth, ourstrwidth(io, compacttype(eltype(col))))
if show_eltype
maxwidths[j] = max(maxwidth, ourstrwidth(io, compacttype(eltype(col))))
else
maxwidths[j] = maxwidth
end
j += 1
end

Expand Down Expand Up @@ -395,6 +400,7 @@ end
allcols::Bool = false,
rowlabel::Symbol = :Row,
displaysummary::Bool = true,
eltypes::Bool = true,
rowid=nothing)

Render a subset of rows (possibly in chunks) of an `AbstractDataFrame` to an
Expand Down Expand Up @@ -422,6 +428,8 @@ NOTE: The value of `maxwidths[end]` must be the string width of
- `displaysummary::Bool`: Should a brief string summary of the
AbstractDataFrame be rendered to the I/O stream before printing the
contents of the renderable rows? Defaults to `true`.
- `eltypes::Bool = true`: Whether to print the column type
under the column name in the heading. Defaults to `true`.
- `rowid = nothing`: Used to handle showing `DataFrameRow`

# Examples
Expand Down Expand Up @@ -449,6 +457,7 @@ function showrows(io::IO,
allcols::Bool = false,
rowlabel::Symbol = :Row,
displaysummary::Bool = true,
eltypes::Bool = true,
rowid=nothing) # -> Void
ncols = size(df, 2)

Expand Down Expand Up @@ -495,23 +504,25 @@ function showrows(io::IO,
end

# Print column types
print(io, "│ ")
padding = rowmaxwidth
for itr in 1:padding
write(io, ' ')
end
print(io, " │ ")
for j in leftcol:rightcol
s = compacttype(eltype(df[!, j]), maxwidths[j], false)
printstyled(io, s, color=:light_black)
padding = maxwidths[j] - ourstrwidth(io, s)
if eltypes
print(io, "│ ")
padding = rowmaxwidth
for itr in 1:padding
write(io, ' ')
end
if j == rightcol
print(io, " │\n")
else
print(io, " │ ")
print(io, " │ ")
for j in leftcol:rightcol
s = compacttype(eltype(df[!, j]), maxwidths[j], false)
printstyled(io, s, color=:light_black)
padding = maxwidths[j] - ourstrwidth(io, s)
for itr in 1:padding
write(io, ' ')
end
if j == rightcol
print(io, " │\n")
else
print(io, " │ ")
end
end
end

Expand Down Expand Up @@ -569,6 +580,7 @@ function _show(io::IO,
splitcols = get(io, :limit, false),
rowlabel::Symbol = :Row,
summary::Bool = true,
eltypes::Bool = true,
rowid=nothing)
_check_consistency(df)
nrows = size(df, 1)
Expand All @@ -590,7 +602,7 @@ function _show(io::IO,
rowindices1 = 1:bound
rowindices2 = max(bound + 1, nrows - nrowssubset + 1):nrows
end
maxwidths = getmaxwidths(df, io, rowindices1, rowindices2, rowlabel, rowid)
maxwidths = getmaxwidths(df, io, rowindices1, rowindices2, rowlabel, rowid, eltypes)
width = getprintedwidth(maxwidths)
showrows(io,
df,
Expand All @@ -601,6 +613,7 @@ function _show(io::IO,
allcols,
rowlabel,
summary,
eltypes,
rowid)
return
end
Expand Down Expand Up @@ -639,6 +652,7 @@ while `splitcols` defaults to `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.

# Examples
```jldoctest
Expand All @@ -662,16 +676,18 @@ Base.show(io::IO,
allcols::Bool = !get(io, :limit, false),
splitcols = get(io, :limit, false),
rowlabel::Symbol = :Row,
summary::Bool = true) =
summary::Bool = true,
eltypes::Bool = true) =
_show(io, df, allrows=allrows, allcols=allcols, splitcols=splitcols,
rowlabel=rowlabel, summary=summary)
rowlabel=rowlabel, summary=summary, eltypes=eltypes)

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) =
summary::Bool = true,
eltypes::Bool = true) =
show(stdout, df,
allrows=allrows, allcols=allcols, splitcols=splitcols,
rowlabel=rowlabel, summary=summary)
rowlabel=rowlabel, summary=summary, eltypes=eltypes)
74 changes: 74 additions & 0 deletions test/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -242,4 +242,78 @@ end
end
end

@testset "eltypes tests" begin
df = DataFrame(A = Int32.(1:3), B = ["x", "y", "z"])

io = IOBuffer()
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 │"""

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 │"""

io = IOBuffer()
show(io, MIME("text/html"), df, eltypes=true)
str = String(take!(io))
@test str == "<table class=\"data-frame\"><thead><tr><th>" *
"</th><th>A</th><th>B</th></tr>" *
"<tr><th></th><th>Int32</th><th>String</th></tr></thead><tbody>" *
"<p>3 rows × 2 columns</p>" *
"<tr><th>1</th><td>1</td><td>x</td></tr>" *
"<tr><th>2</th><td>2</td><td>y</td></tr><tr><th>3</th><td>3</td><td>z</td></tr></tbody></table>"

io = IOBuffer()
show(io, MIME("text/html"), df, eltypes=false)
str = String(take!(io))
@test str == "<table class=\"data-frame\"><thead><tr><th>" *
"</th><th>A</th><th>B</th></tr></thead><tbody>" *
"<p>3 rows × 2 columns</p>" *
"<tr><th>1</th><td>1</td><td>x</td></tr>" *
"<tr><th>2</th><td>2</td><td>y</td></tr><tr><th>3</th><td>3</td><td>z</td></tr></tbody></table>"

io = IOBuffer()
show(io, MIME("text/latex"), df, eltypes=true)
str = String(take!(io))
@test str == """
\\begin{tabular}{r|cc}
\t& A & B\\\\
\t\\hline
\t& Int32 & String\\\\
\t\\hline
\t1 & 1 & x \\\\
\t2 & 2 & y \\\\
\t3 & 3 & z \\\\
\\end{tabular}
"""

io = IOBuffer()
show(io, MIME("text/latex"), df, eltypes=false)
str = String(take!(io))
@test str == """
\\begin{tabular}{r|cc}
\t& A & B\\\\
\t\\hline
\t1 & 1 & x \\\\
\t2 & 2 & y \\\\
\t3 & 3 & z \\\\
\\end{tabular}
"""
end

end # module
27 changes: 27 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -460,4 +460,31 @@ end
│ 1 │ missing │"""
end

@testset "wide type name" begin
df = DataFrame(A = Int32.(1:3), B = ["x", "y", "z"])

io = IOBuffer()
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 │"""

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 │"""
end

end # module