# Is there a better way to format each individual columns in a dataframe?

**URL:** <https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677>\
**Category:** General Usage\
**Tags:** dataframes, prettytables\
**Created:** [March 15, 2024, 6:41pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677 "2024-03-15T18:41:45Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Philip\_Stuckey](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/philip_stuckey/32/4000_2.png) [@Philip\_Stuckey](https://discourse.julialang.org/u/Philip_Stuckey)\
**Post date:** [March 15, 2024, 6:41pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677/1 "2024-03-15T18:41:45Z")

</div>

I wrote a function to format individual columns of a dataframe and I’m wondering if that’s a good idea or not.

Is there a better way to format the columns of a dataframe before printing to markdown? I found the formatters in `PrettyTables` difficult to use so I wrote the function

```julia
using DataStructures: DefaultDict
using Format
using DataFrames
function format_columns(table; formats...)
    formats = DefaultDict("{}", formats...)
    return DataFrame(
        [k=>format.(formats[Symbol(k)], table[!,k]) for k in names(table)]
    )
end

```

So I could do this:

```julia
format_columns(table, 
foo="{:0.1f}",
bar="{:0.2f}",
baz="{:0.2f} dB",
qux="{:0.1%}"
)

```

and get

```julia
5×4 DataFrame
 Row │ foo bar baz qux
     │ String String String String
─────┼──────────────────────────────────
   1 │ 1.0 0.00 0.00 dB 100.0%
   2 │ 1.1 0.05 -0.01 dB 99.8%
   3 │ 1.2 0.09 -0.04 dB 99.2%
   4 │ 1.3 0.13 -0.07 dB 98.3%
   5 │ 1.4 0.17 -0.12 dB 97.2%

```

Is there an easier way to do this?  
Would this be useful to anyone as a package?  
Given that I can’t find any other way to do this, I feel like either this isn’t a thing people need to do or my approach is subtly wrong.

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 15, 2024, 7:58pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677/2 "2024-03-15T19:58:26Z")

</div>

first of all, it occurs to me that these aspects may be in the scope of the prettytables.jl package.  
Dataframe columns are more easily/efficiently transformed/combined if they maintain the appropriate type.

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 15, 2024, 7:59pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677/3 "2024-03-15T19:59:16Z")

</div>

With PrettyTables, it may be written like this:

```julia
using DataFrames, PrettyTables

df = DataFrame(rand(5,4), [:foo, :bar, :baz, :qux])

dic = Dict([:foo, :bar, :baz, :qux] .=> ["%0.1f", "%0.2f", "%0.2f dB", "%0.1f%%"])
d = Dict(Symbol.(names(df)) .=> 1:ncol(df))

pretty_table(df, formatters = ft_printf(collect(values(dic)), getindex.(Ref(d), keys(dic))))

```

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 15, 2024, 8:03pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677/4 "2024-03-15T20:03:44Z")

</div>

And an alternative way using `Printf`:

```julia
using DataFrames, Printf

df = DataFrame(rand(5,4), [:foo, :bar, :baz, :qux])

dic = Dict([:foo, :bar, :baz, :qux] .=> ["%0.1f", "%0.2f", "%0.2f dB", "%0.1f%%"])
dg = string.(df)
for (key, val) in dic
    fmt = Printf.Format(val)
    dg[!, key] = Printf.format.(Ref(fmt), df[!, key])
end
dg

```

---

<div class="post-metadata">

**Author:** ![rocco\_sprmnt21](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rocco_sprmnt21/32/20127_2.png) [@rocco\_sprmnt21](https://discourse.julialang.org/u/rocco_sprmnt21)\
**Post date:** [March 15, 2024, 8:08pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677/5 "2024-03-15T20:08:51Z")

</div>

As far as you know, PrettyTables only acts on the external aspect of the format (redefines show for example)? But do the columns of the dataframe retain their original type?

---

<div class="post-metadata">

**Author:** ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)\
**Post date:** [March 15, 2024, 8:32pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677/6 "2024-03-15T20:32:24Z")

</div>

Yes

---

<div class="post-metadata">

**Author:** ![GHTaarn](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ghtaarn/32/216007_2.png) [@GHTaarn](https://discourse.julialang.org/u/GHTaarn)\
**Post date:** [March 16, 2024, 5:48pm UTC](https://discourse.julialang.org/t/is-there-a-better-way-to-format-each-individual-columns-in-a-dataframe/111677/7 "2024-03-16T17:48:20Z")

</div>

The code for formatting columns with `PrettyTables` and `Printf` is quite quite a lot, so I wrote a little package that can do this [GitHub - GHTaarn/PrettyDataFrames.jl: DataFrames with custom formatting of each column of data](https://github.com/GHTaarn/PrettyDataFrames.jl)

I would have liked it to be a subtype of `AbstractDataFrame`, but this appears to be a lot of work, so that will have to be a future project if this feature does not get into `DataFrames` itself.
