Question about plotting panel data?

Dear all,

In Stata, we can easily use xtline to plot the graph of panel data.

webuse grunfeld,clear
xtline invest

In Julia, How can I plot this graph?

julia> using RDatasets

julia> using DataFrames

julia> df = dataset("plm", "Grunfeld");

julia> using DataFrames

julia> using DataFramesMeta

julia> using RDatasets

julia> df = dataset("plm", "Grunfeld");

julia> gd = groupby(df, :Firm);

julia> p = plot(layout = 10)

julia> for i in 1:gd.ngroups
           data = @where(df, :Firm .== i)
           @df data plot!(p[i], :Year, :Inv)
       end

julia> display(p)

This is maybe not the best way to plot this graph.

AlgebraOfGraphics is pretty good for this.

using RDatasets
using DataFrames
using AlgebraOfGraphics, CairoMakie
df = dataset("plm", "Grunfeld");

plt = data(df) * mapping(:Year, :Inv, layout=:Firm => nonnumeric) * visual(Lines)
draw(plt)

:Firm => nonnumeric is required because the Firm column is an integer; otherwise, it would just be :Firm.

1 Like

Thanks so much. It is a better way to visualize panel data.

It seems not work.

julia> using RDatasets

julia> using DataFrames

julia> using AlgebraOfGraphics, CairoMakie
[ Info: Precompiling AlgebraOfGraphics [cbdf2221-f076-402e-a563-3d30da359d67]

julia> df = dataset("plm", "Grunfeld");

julia> plt = data(df) * mapping(:Year, :Inv, layout=:Firm => nonnumeric) * visual(Lines)
ERROR: UndefVarError: nonnumeric not defined
Stacktrace:
 [1] top-level scope
   @ REPL[26]:1

Hmm, you may have an out-of-date version of AlgebraOfGraphics and/or Julia. It looks like nonnumeric was introduced in v0.4 of AlgebraOfGraphics.
You can check the package version like

julia> import Pkg; Pkg.status()
      Status `C:\Users\evan\.julia\environments\v1.7\Project.toml`
  [cbdf2221] AlgebraOfGraphics v0.6.7
  [6e4b80f9] BenchmarkTools v1.3.1   
  [13f3f980] CairoMakie v0.8.3       
  [324d7699] CategoricalArrays v0.10.6
  [861a8166] Combinatorics v1.0.2
  [a93c6f00] DataFrames v1.3.4
  [864edb3b] DataStructures v0.18.13
  [abce61dc] Decimals v0.4.1
  [f6369f11] ForwardDiff v0.10.30
  [6fe1bfb0] OffsetArrays v1.12.1
  [27ebfcd6] Primes v0.5.2
  [ce6b1742] RDatasets v0.7.7
  [a759f4b9] TimerOutputs v0.5.19

You could try updating with julia> import Pkg; Pkg.update() but this updates all packages, which may break other things.

nonnumeric used to be called categorical according to the release notes, so you could also try

plt = data(df) * mapping(:Year, :Inv, layout=:Firm => categorical) * visual(Lines)

If that still doesnโ€™t work, you can manually convert the Firm column to a categorical array.

using CategoricalArrays
df[!,:Firm] = categorical(df[:,:Firm]);
plt = data(df) * mapping(:Year, :Inv, layout=:Firm) * visual(Lines);
draw(plt)
(zhangdeliang) pkg> st
      Status `~/Project.toml`
  [cbdf2221] AlgebraOfGraphics v0.6.7
  [13f3f980] CairoMakie v0.8.3
  [e9467ef8] GLMakie v0.6.3
  [7073ff75] IJulia v1.23.3
  [49802e3a] ProgressBars v1.4.1
  [ce6b1742] RDatasets v0.7.7
  [3cdcf5f2] RecipesBase v1.2.1
  [d1185830] SymbolicUtils v0.19.7
  [fce5fe82] Turing v0.21.3

Hmm, does this raise the same error?

julia> AlgebraOfGraphics.nonnumeric(3)
AlgebraOfGraphics.NonNumeric{Int64}(3)
julia> using RDatasets

julia> using DataFrames

julia> using AlgebraOfGraphics, CairoMakie

julia> df = dataset("plm", "Grunfeld");

julia> plt = data(df) * mapping(:Year, :Inv, layout=:Firm => nonnumeric) * visual(Lines)
Layer(AlgebraOfGraphics.Visual(Lines, {}), 200ร—5 DataFrameColumns
 Row โ”‚ Firm   Year   Inv      Value    Capital 
     โ”‚ Int64  Int64  Float64  Float64  Float64 
โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
   1 โ”‚     1   1935   317.6   3078.5      2.8
   2 โ”‚     1   1936   391.8   4661.7     52.6
   3 โ”‚     1   1937   410.6   5387.1    156.9
   4 โ”‚     1   1938   257.7   2792.2    209.2
   5 โ”‚     1   1939   330.8   4313.2    203.4
   6 โ”‚     1   1940   461.2   4643.9    207.2
   7 โ”‚     1   1941   512.0   4551.2    255.2
   8 โ”‚     1   1942   448.0   3244.1    303.7
  โ‹ฎ  โ”‚   โ‹ฎ      โ‹ฎ       โ‹ฎ        โ‹ฎ        โ‹ฎ
 194 โ”‚    10   1948     5.66    68.0      5.38
 195 โ”‚    10   1949     4.21    71.24     7.39
 196 โ”‚    10   1950     3.42    69.05     8.74
 197 โ”‚    10   1951     4.67    83.04     9.07
 198 โ”‚    10   1952     6.0     74.42     9.93
 199 โ”‚    10   1953     6.53    63.51    11.68
 200 โ”‚    10   1954     5.12    58.12    14.33
                               185 rows omitted, Any[:Year, :Inv], {:layout = :Firm => AlgebraOfGraphics.nonnumeric})

julia> draw(plt)
Scene (800px, 600px):
  0 Plots
  22 Child Scenes:
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”” Scene (800px, 600px)

So thereโ€™s no more error, but itโ€™s not drawing the plot now?
Sorry I am not very adept at the plotting ecosystemโ€ฆ maybe someone with more experience could chime in.

Yes, there is no error now. But no graph.
Thanks.

julia> draw(plt)
Scene (800px, 600px):
  0 Plots
  22 Child Scenes:
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”œ Scene (800px, 600px)
    โ”” Scene (800px, 600px)

Sorry, I missed the draw call. Are you executing this directly from the REPL? It should show in Pluto or VSCode. Otherwise you might want to have a look at ElectronDisplay.jl for plotting directly from the REPL.

Yes, I run it from REPL. I will try ElectronDisplay.jl. Thanks.

You can also just do fig = draw(plt) and then save(โ€œmyplot.svgโ€, fig) to save the figure to disk.

Yeah, youโ€™ll have to have some sort of display open. You can also use GLMakie for a desktop plot or WGLMakie for in-browser plots.

If you need to use CairoMakie, you can always save the plot and inspect it using an image viewer, i.e., save("filename.pdf", fig).

I raised a similar question here thought it was somehow ignored. :sweat_smile:
It refers to PlotlyJS. I managed to produce a good output, but not without pain.
I now simplified a bit the code with a for loop to produce each graphic in the panel.