Reputation: 51
This works:
StatsPlots.@df SYN_MM_BM_df plot(
:t,
[:SYN_MM_BM_5, :SYN_MM_BM_10, :SYN_MM_BM_15, :SYN_MM_BM_30]
)
But this does not:
StatsPlots.@df SYN_MM_BM_df plot(
:t,
[Symbol(name) for name in names(SYN_MM_BM_df[2:5])]
)
Error: Cannot convert Symbol to series data for plotting
Although:
[Symbol(name) for name in names(SYN_MM_BM_df)[2:5]] ==
[:SYN_MM_BM_5, :SYN_MM_BM_10, :SYN_MM_BM_15, :SYN_MM_BM_30
is true.
Can anyone explain why? I'd really like to not type all the symbols individually...
Upvotes: 5
Views: 1502
Reputation: 13800
The reason for this is that @df
is a macro, not a function, which means that it transforms the code you write into different code before any code is actually run. That is, it operates on the expression [Symbol(name) for name in names(df)[2:5]]
before it actually gets evaluated (and thereby turned into [:SYN_MM_BM_5 ...]
.
To illustrate the difference, you can use @macroexpand
(here in conjuction with prettify
from MacroTools
to make the output a bit more readable:
julia> using DataFrames, StatsPlots, MacroTools
julia> df = DataFrame(a = 1:10, b = 10 .* rand(10), c = 10 .* rand(10));
# Calling macro with symbols written out
julia> prettify(@macroexpand(@df df plot(:a, [:b, :c], colour = [:red :blue])))
:(((crane->begin
((rat, zebra, coyote, butterfly, starling), curlew) = (StatsPlots).extract_columns_and_names(crane, :a, :b, :c, :red, :blue)
(StatsPlots).add_label(["a", "[b, c]"], plot, rat, [zebra, coyote], colour = [butterfly starling])
end))(df))
# Calling macro with comprehension
julia> prettify(@macroexpand(@df df plot(:a, [x for x ∈ names(df)[2:3]], colour = [:red :blue])))
:(((crane->begin
((rat, zebra, coyote), butterfly) = (StatsPlots).extract_columns_and_names(crane, :a, :red, :blue)
(StatsPlots).add_label(["a", "[x for x = (names(df))[23]]"], plot, rat, [x for x = (names(df))[2:3]], colour = [zebra coyote])
end))(df))
As you see, the comprehension does not get picked up by the macro, and you therefore end up calling StatsPlots.extract_columns_and_names(df, :a, :red, :blue)
instead of StatsPlots.extract_columns_and_names(df, :a, :b, :c, :red, :blue)
.
I see that Bogumil has already provided the solution to this as I was typing, looks like my StatsPlots
was too slow to precompile :)
Upvotes: 4
Reputation: 69819
To work around the limitation that @Nils Gudat highlighted use cols
(it treats its contents as a variable and expands it to columns) to get what you want (and use propertynames
on data frame to get its column names as symbols directly):
julia> df = DataFrame(x=1:10, y=rand(10), z=rand(10));
julia> @df df plot(:x, cols(propertynames(df)[2:end]))
which is what I assume you want.
Upvotes: 4