拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 如何在ggplot中创建具有两个长度不等的资料集和两层图的绘图函式?

如何在ggplot中创建具有两个长度不等的资料集和两层图的绘图函式?

白鹭 - 2022-03-09 2106 0 0

我有一个名为的资料集df1,如下所示:

category    subject    runtime
foo         square     7.3
foo         circle.    10.5
foo2        square     15.3    
...

还有一个名为 的第二个子集df2,我在其中过滤categoryn > 1 的位置,这会导致较小的资料帧category==foo2被洗掉:

category    subject    runtime
foo         square     7.3
foo         circle.    10.5
...

我尝试在一个函式中绘制这两个资料集,该函式将创建一个箱线图(对于所有出现多次 的行category,因此我在df2这里使用geom_boxplot子集和点图来表示只有一次出现的category。例如:

create.my.plot <- function(df, df.subset, xaxis, yaxis, xlab, ylab) {
  ex.plot <- ggplot(df, aes(x=xaxis, y=yaxis)) 
    geom_boxplot(data = df.subset, aes(fill=xaxis))  
    geom_point(position="identity", size=1)  
    labs(x=xlab, y=ylab)
  ex.plot
}

我可以在这个绘图函式之外很好地创建这个图,但是当我从这个函式呼叫它时,它回传一个关于资料帧长度的错误:

> create.my.plot(df1, df2, df$category, df$runtime, "Category", "Runtime")
Error: Aesthetics must be either length 1 or the same as the data (3): x and y

我想这是因为当ggplot()被呼叫时,它与df并期望变量在?aes()中具有行数df

我更喜欢使用绘图功能,因为我必须重复创建绘图但是如何克服这个错误,我需要使用不等长度的不同资料集来绘制图层?

uj5u.com热心网友回复:

问题是您用来df$...将要绘制的变量传递给您的函式。你得到的错误是为什么作为一般规则你永远不应该使用df$...inside的原因之一aes()

而是将您的列作为不带引号的名称传递给函式,并在内部使用{{(= curly-curly) aes()

library(ggplot2)

create.my.plot <- function(df, df.subset, xaxis, yaxis, xlab, ylab) {
  ggplot(df, aes(x = {{ xaxis }}, y = {{ yaxis }}))  
    geom_boxplot(data = df.subset, aes(fill = {{ xaxis }}))  
    geom_point(position = "identity", size = 1)  
    labs(x = xlab, y = ylab)
}

create.my.plot(df1, df2, category, runtime, "x", "y")

如何在ggplot中创建具有两个长度不等的资料集和两层图的绘图函式?

或者作为第二个选项,将列名作为带引号的字符串传递并使用.data代词:

create.my.plot1 <- function(df, df.subset, xaxis, yaxis, xlab, ylab) {
  ggplot(df, aes(x = .data[[xaxis]], y = .data[[yaxis]]))  
    geom_boxplot(data = df.subset, aes(fill = .data[[xaxis]]))  
    geom_point(position = "identity", size = 1)  
    labs(x = xlab, y = ylab)
}

create.my.plot1(df1, df2, "category", "runtime", "x", "y")

如何在ggplot中创建具有两个长度不等的资料集和两层图的绘图函式?

资料

df1 <- data.frame(
  category = c("foo", "foo", "foo2"),
  subject = c("square", "circle", "square"),
  runtime = 1:3
)
df2 <- df1[df1$category != "foo2", ]

uj5u.com热心网友回复:

Stefan 的回答很好,但会绘制与箱线图相关的所有点。我会建议这样做(我使资料更加真实)。首先,资料如下:

df1 <- data.frame(
  category = factor(rep(c("foo", "foo3", "foo2"), c(100,100, 1))),
  subject = sample(c("circle", "square"), 201, replace=TRUE),
  runtime = runif(201, 5, 25)
)

接下来,在您的资料中创建一个新变量来计算每组的观察次数。

df1 <- df1 %>% 
  group_by(category) %>% 
  mutate(n = n())

将资料过滤为将用点绘制的资料和用方框绘制的资料:

df_pt <- df1 %>% 
  filter(n == 1)
df_box <- df1 %>% 
  filter(n > 1)

然后,可以修改该函式以使用点和框资料集。重要的是点资料集将包含所有点

create.my.plot1 <- function(df.point, df.box, xaxis, yaxis, xlab, ylab) {
  ggplot()  
    geom_point(data=df.point, aes_string(x = xaxis, y = yaxis), 
               position = "identity", size = 1)  
    geom_boxplot(data = df.box, aes_string(x=xaxis, y=yaxis, fill = xaxis))  
    labs(x = xlab, y = ylab)
}

最后,在您的资料上呼叫绘图:

create.my.plot1(df_pt, df_box, "category", "runtime", "x", "y")

如何在ggplot中创建具有两个长度不等的资料集和两层图的绘图函式?

或者,您也可以构建函式来为您完成所有子集作业:

df1 <- data.frame(
  category = factor(rep(c("foo", "foo3", "foo2"), c(100,100, 1))),
  subject = sample(c("circle", "square"), 201, replace=TRUE),
  runtime = runif(201, 5, 25)
)
create.my.plot1 <- function(dat, xaxis, yaxis, xlab, ylab) {
  x <- dat %>% 
    group_by(across(all_of(xaxis))) %>% 
    mutate(n = n())
  pt <- x %>% filter(n == 1)
  box <- x %>% filter(n > 1)
  cat("Number of sinlge points: ", nrow(pt), "\nNumber of boxes: ", length(table(box[[xaxis]])), "\n")
  ggplot()  
    geom_point(data=pt, aes_string(x = xaxis, y = yaxis), 
               position = "identity", size = 1)  
    geom_boxplot(data = box, aes_string(x=xaxis, y=yaxis, fill = xaxis))  
    labs(x = xlab, y = ylab)
}

create.my.plot1(df1, "category", "runtime", "x", "y")

结果与上述相同。

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *