【问题标题】:What is Julia's equivalent ggplot code of R's?什么是 Julia 的 R 等效 ggplot 代码?
【发布时间】:2021-11-23 23:47:06
【问题描述】:

我想在 Julia 中绘制一个复杂的图表。下面的代码是使用 ggplot 的 Julia 版本。

using CairoMakie, DataFrames, Effects, GLM, StatsModels, StableRNGs, RCall
@rlibrary ggplot2

rng = StableRNG(42)
growthdata = DataFrame(; age=[13:20; 13:20],
                       sex=repeat(["male", "female"], inner=8),
                       weight=[range(100, 155; length=8); range(100, 125; length=8)] .+ randn(rng, 16))

mod_uncentered = lm(@formula(weight ~ 1 + sex * age), growthdata)

refgrid = copy(growthdata)
filter!(refgrid) do row
    return mod(row.age, 2) == (row.sex == "male")
end
effects!(refgrid, mod_uncentered)

refgrid[!, :lower] = @. refgrid.weight - 1.96 * refgrid.err
refgrid[!, :upper] = @. refgrid.weight + 1.96 * refgrid.err

df= refgrid

ggplot(df, aes(x=:age, y=:weight, group = :sex, shape= :sex, linetype=:sex)) + 
  geom_point(position=position_dodge(width=0.15)) +
  geom_ribbon(aes(ymin=:lower, ymax=:upper), fill="gray", alpha=0.5)+
  geom_line(position=position_dodge(width=0.15)) + 
  ylab("Weight")+ xlab("Age")+
  theme_classic()

但是,我想再修改一下这个图表。例如,我想更改 y 轴的比例、功能区的颜色、添加一些误差线,以及更改图例的文本大小等等。由于我是 Julia 新手,因此我没有成功找到这些修改的等效语言代码。有人可以帮我将 ggplot 下面的 R 代码翻译成 Julia 的语言吗?

t1= filter(df, sex=="male") %>% slice_max(df$weight) 


ggplot(df, aes(age, weight, group = sex, shape= sex, linetype=sex,fill=sex, colour=sex)) + 
  geom_line(position=position_dodge(width=0.15)) +
  geom_point(position=position_dodge(width=0.15)) +
  geom_errorbar(aes(ymin = lower, ymax = upper),width = 0.1,
                linetype = "solid",position=position_dodge(width=0.15))+
  geom_ribbon(aes(ymin = lower, ymax = upper, fill = sex, colour = sex), alpha = 0.2) +
  geom_text(data = t1, aes(age, weight, label = round(weight, 1)), hjust = -0.25, size=7,show_guide  = FALSE) +
  scale_y_continuous(limits = c(70, 150), breaks = seq(80, 140, by = 20))+
  theme_classic()+
  scale_colour_manual(values = c("orange", "blue")) +
  guides(color = guide_legend(override.aes = list(linetype = c('dotted', 'dashed'))),
         linetype = "none")+
  xlab("Age")+ ylab("Average marginal effects") + ggtitle("Title") +
  theme( 
    axis.title.y = element_text(color="Black", size=28, face="bold", hjust = 0.9),
    axis.text.y = element_text(face="bold", color="black", size=16),
    plot.title = element_text(hjust = 0.5, color="Black", size=28, face="bold"),
    legend.title = element_text(color = "Black", size = 13),
    legend.text = element_text(color = "Black", size = 16),
    legend.position="bottom",
    axis.text.x = element_text(face="bold", color="black", size=11),
    strip.text = element_text(face= "bold", size=15)
  ) 

【问题讨论】:

  • 你读过情节documentation/tutorials 吗?您可以开始编写您的情节,然后您可以在这里搜索或询问您遇到的具体问题..
  • AlgebraOfGraphics 是 Julia 中类似 ggplot 的声明式绘图 API。 Plots.jl 是一个类似于 matplotlib 的命令式 API。
  • @Antonello,是的,我查看了 Julia 中的一些绘图包。但我暂时还是想使用ggplot,因为我认为它更灵活、更高效
  • AlgebraOfGraphics 试图到达那里,但作为一个真正的 ggplot 粉丝,它还不能满足我(并且确实缺乏 R 的非标准评估)。所以现在,我导出结果并在 R 中进行绘图。(不过,AoG 已经很酷了!)
  • 某些功能没有在 Julia 中记录的一个原因是因为它们不太适用(在某些情况下令人惊讶)。例如,测量包允许我使用 59.8 ± 5.0 之类的值。然后,当我绘制这些值时,我会在图中得到误差线,而我没有任何明确的行动。这在 Plots 文档中不会显示为整个部分,因为它是一个紧急属性。 Plots 包真的不知道这一点,因此无法记录它。在 ggplots 中,他们必须记录所有这些事情,因为没有协同作用。

标签: ggplot2 julia


【解决方案1】:

我使用了同样基于“图形语法”的 Vega-Lite (https://github.com/queryverse/VegaLite.jl),以及提供与 GLM 相似功能的 LinearRegression (https://github.com/ericqu/LinearRegression.jl),尽管我认为可以通过其他绘图和线性回归包。不过,我希望这可以为您提供一个起点。

using LinearRegression: Distributions, DataFrames, CategoricalArrays
using DataFrames, StatsModels, LinearRegression
using VegaLite

growthdata = DataFrame(; age=[13:20; 13:20],
                       sex=categorical(repeat(["male", "female"], inner=8), compress=true),
                       weight=[range(100, 155; length=8); range(100, 125; length=8)] .+ randn(16))

lm = regress(@formula(weight ~ 1 + sex * age), growthdata)

results = predict_in_sample(lm, growthdata, req_stats="all")

fp = select(results, [:age, :weight, :sex, :uclp, :lclp, :predicted]) |> @vlplot() +
@vlplot(
    mark = :errorband, color = :sex,
    y = { field = :uclp, type = :quantitative, title="Average marginal effects"}, 
    y2 = { field = :lclp, type = :quantitative }, 
    x = {:age, type = :quantitative} ) + 
@vlplot(
    mark = :line, color = :sex,
    x = {:age, type = :quantitative},
    y = {:predicted, type = :quantitative}) +
@vlplot(
    :point, color=:sex ,
    x = {:age, type = :quantitative, axis = {grid = false}, scale = {zero = false}},
    y = {:weight, type = :quantitative, axis = {grid = false}, scale = {zero = false}},
    title = "Title", width = 400 , height = 400
)

给出:

您可以通过更改此处指示的“配置”来更改元素的样式 (https://www.queryverse.org/VegaLite.jl/stable/gettingstarted/tutorial/#Config-1)。

由于 Julia Vega-Lite 是 Vega-Lite 的包装器,因此可以在 Vega-lite 网站 (https://vega.github.io/vega-lite/) 上找到其他文档

【讨论】:

    【解决方案2】:

    正如我之前所说,您可以使用 R 字符串来运行 R 代码。需要明确的是,这不像你的帖子的方法,你将许多 Julia 对象拼凑在一起,这些对象包含许多 R 对象,这是 RCall 将 Julia 数据帧转换为 R 数据帧,然后运行你的 R 代码。

    运行 R 脚本可能看起来不太儒雅,但代码重用却很儒雅。此外,无论哪种方式,您仍在使用 R 库和活动 R 会话,甚至可能通过减少创建包装对象和在 Julia 和 R 之间切换的频率来稍微提高性能。

    ## import libraries for Julia and R; still good to do at top
    
    using CairoMakie, DataFrames, Effects, GLM, StatsModels, StableRNGs, RCall
    R"""
    library(ggplot2)
    library(dplyr)
    """
    
    ## your Julia code without the @rlibrary or ggplot lines
    
    rng = StableRNG(42)
    growthdata = DataFrame(; age=[13:20; 13:20],
                           sex=repeat(["male", "female"], inner=8),
                           weight=[range(100, 155; length=8); range(100, 125; length=8)] .+ randn(rng, 16))
    
    mod_uncentered = lm(@formula(weight ~ 1 + sex * age), growthdata)
    
    refgrid = copy(growthdata)
    filter!(refgrid) do row
        return mod(row.age, 2) == (row.sex == "male")
    end
    effects!(refgrid, mod_uncentered)
    
    refgrid[!, :lower] = @. refgrid.weight - 1.96 * refgrid.err
    refgrid[!, :upper] = @. refgrid.weight + 1.96 * refgrid.err
    
    df= refgrid
    
    ## convert Julia's df and run your R code in R-string
    ## - note that $df is interpolation of Julia's df into R-string,
    ##   not R's $ operator like in rdf$weight
    ## - call the R dataframe rdf because df is already an R function
    
    R"""
    rdf <- $df
    t1= filter(rdf, sex=="male") %>% slice_max(rdf$weight) 
    
    ggplot(rdf, aes(age, weight, group = sex, shape= sex, linetype=sex,fill=sex, colour=sex)) + 
      geom_line(position=position_dodge(width=0.15)) +
      geom_point(position=position_dodge(width=0.15)) +
      geom_errorbar(aes(ymin = lower, ymax = upper),width = 0.1,
                    linetype = "solid",position=position_dodge(width=0.15))+
      geom_ribbon(aes(ymin = lower, ymax = upper, fill = sex, colour = sex), alpha = 0.2) +
      geom_text(data = t1, aes(age, weight, label = round(weight, 1)), hjust = -0.25, size=7,show_guide  = FALSE) +
      scale_y_continuous(limits = c(70, 150), breaks = seq(80, 140, by = 20))+
      theme_classic()+
      scale_colour_manual(values = c("orange", "blue")) +
      guides(color = guide_legend(override.aes = list(linetype = c('dotted', 'dashed'))),
             linetype = "none")+
      xlab("Age")+ ylab("Average marginal effects") + ggtitle("Title") +
      theme( 
        axis.title.y = element_text(color="Black", size=28, face="bold", hjust = 0.9),
        axis.text.y = element_text(face="bold", color="black", size=16),
        plot.title = element_text(hjust = 0.5, color="Black", size=28, face="bold"),
        legend.title = element_text(color = "Black", size = 13),
        legend.text = element_text(color = "Black", size = 16),
        legend.position="bottom",
        axis.text.x = element_text(face="bold", color="black", size=11),
        strip.text = element_text(face= "bold", size=15)
      ) 
    """
    

    结果与您帖子的 R 代码相同:

    【讨论】:

      猜你喜欢
      • 2021-08-27
      • 2019-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-06
      • 2017-06-09
      • 1970-01-01
      相关资源
      最近更新 更多