به‌روزرسانی بسته ggplot2 +تغییرات ۴.۰

ggplot2-4 (1)

وبلاگ TidyVerse 1 خبر از انتشار نسخه جدید بسته ggplot2 داد و تغییرات زیاد این به‌روزرسانی، دلیلی شده تا شماره اصلی این بسته را نیز به روز کنند و به ورژن 4.0 رسید.  این بسته که بر اساس کتاب The Grammar of Graphics طراحی شده است به کاربران اجازه می‌دهد تا با تعریف اجزای اصلی نمودار شامل داده‌ها، متغیرها، سیستم مختصات و عناصر گرافیکی، نمودارهای پیچیده را به صورت لایه‌ای و ماژولار بسازند. ggplot2 امکان ایجاد طیف گسترده‌ای از نمودارها – از نمودارهای پراکندگی ساده تا نقشه‌های چندلایه و نمودارهای آماری پیشرفته – را با حداقل کد و حداکثر انعطاف‌پذیری فراهم می‌کند. این بسته به دلیل قابلیت‌های سفارشی‌سازی بالا، پشتیبانی از تم‌های یکپارچه و سازگاری با اکوسیستم tidyverse، به ابزاری استاندارد در تحلیل داده‌ها و مصورسازی علمی تبدیل شده است.

نسخه جدید را می‌توان از CRAN با دستور زیر نصب کرد:

install.packages("ggplot2")
R

این نسخه شامل تغییرات قابل توجهی است که دلیلی برای تغییر شماره اصلی نسخه شده است. مهم‌ترین تغییرات شامل بازنویسی سیستم شیءگرا از S3 به S7، اضافه شدن ویژگی‌های جدید، بهبودهای کاربردی و رفع اشکالات است. همچنین هجدهمین سالگرد انتشار این بسته گرامی داشته می‌شود. در این متن، برجسته‌ترین ویژگی‌های جدید این نسخه معرفی می‌شوند. لیست کامل تغییرات در یادداشت‌های انتشار قابل مشاهده است.

انتقال به S7

در ggplot2، افزایش شماره اصلی نسخه نشان‌دهنده تغییرات اساسی در هسته بسته است. در این نسخه، بسیاری از اشیاء S3 با اشیاء S7 جایگزین شده‌اند. S7 مانند S3 و S4 یک سیستم شیءگرا مبتنی بر کلاس، توابع عمومی و متدهاست که سعی می‌کند بین انعطاف‌پذیری S3 و ساختارمند بودن S4 تعادل ایجاد کند.

این تغییر برای کاربران معمولی که فقط از ggplot2 برای ساخت نمودار استفاده می‌کنند، چندان محسوس نخواهد بود. شاید تنها تفاوت قابل توجه، اعتبارسنجی سختگیرانه‌تر انواع داده‌ها باشد. برای مثال، ورودی‌های نامعتبر اکنون بلافاصله رد می‌شوند:

element_text(hjust = "foo")
#> Error: <ggplot2::element_text> object properties are invalid:
#> - @hjust must be <NULL>, <integer>, or <double>, not <character>
R

اما اگر از قابلیت‌های داخلی ggplot2 به روش‌های غیرمعمول استفاده می‌کنید، ممکن است نیاز به تنظیمات داشته باشید. برای توسعه‌دهندگان افزونه‌ها، مزیت اصلی S7 امکان استفاده از double dispatch است که به خصوص برای تابع update_ggplot() (جانشین ggplot_add()) مهم است. این تابع کنترل بیشتری بر رفتار عملگر + هنگام افزودن اشیاء به نمودار فراهم می‌کند.

برای حفظ سازگاری با بسته‌های موجود، برخی ویژگی‌های قدیمی به طور موقت حفظ شده‌اند (مانند دسترسی به داده‌ها با ggplot()$data). این ویژگی‌ها به تدریج حذف خواهند شد و راهنمای مهاجرت از S3 به S7 برای بسته‌های مرتبط در حال آماده‌سازی است.

بهبودهای طراحی

تم‌ها در ggplot2 مسئول کنترل ظاهر نمودارها هستند. در این نسخه، پیش‌فرض‌های ظاهری لایه‌ها (مانند شکل نقاط و پالت رنگ) نیز به تم‌ها منتقل شده‌اند. این ایده که پیش‌فرض‌های لایه‌ها باید بخشی از تم باشند، مدتی است مطرح بوده و اکنون پیاده‌سازی شده است.

جوهر و کاغذ

پیش‌فرض‌های جدید لایه‌ها با مفاهیم ink (پیش‌زمینه) و paper (پس‌زمینه) کار می‌کنند که با ویژگی‌های colour و fill متفاوت هستند. برای مثال  یک نمودار جعبه‌ای بدون colour قابل خواندن نیست، اما بدون fill کاملاً قابل تفسیر است. در مورد نمودار جعبه‌ای، وضوح ink را colour باید دید و در حالی که paper در fill قرار می‌گیرد. در نمودارهای میله‌ای یا هیستوگرام‌ها، اصل تناسب جوهر تصریح می‌کند که زیبایی‌شناسی fill ، پیش‌زمینه در نظر گرفته می‌شود و بنابراین به عنوان ink در نظر گرفته می‌شود.

این سه گزینه به تمام تم‌های داخلی اضافه شده‌اند و هم بر پیش‌فرض‌های لایه‌ها و هم بر سایر اجزای تم تأثیر می‌گذارند. برای سفارشی‌سازی تم، می‌توان از theme(geom) و تابع جدید element_geom() استفاده کرد. برای دسترسی به این مقادیر در نگاشت‌ها، تابع from_theme() در دسترس است.

ggplot(mpg, aes(displ, hwy)) +
  geom_point() +
  geom_smooth(method = "lm", formula = y ~ x) +
  theme_gray(paper = "cornsilk", ink = "navy", accent = "tomato")
R
image | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

اگر در حال سفارشی‌سازی یک قالب هستید، می‌توانید از آرگومان theme(geom) برای تنظیم مجموعه‌ای از پیش‌فرض‌ها استفاده کنید. تابع جدید element_geom() می‌تواند برای تنظیم این ویژگی‌ها استفاده شود. علاوه بر این، اگر می‌خواهید یک لایه، ویژگی را از این عنصر تم بخواند، می‌توانید از تابع from_theme() در نگاشت برای دسترسی به این متغیرها استفاده کنید.

ggplot(mpg, aes(class, displ)) +
  geom_boxplot(aes(colour = from_theme(accent))) +
  theme(
    geom = element_geom(accent = "tomato", paper = "cornsilk")
  )
R
image 1 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

دومین تفاوت مفهومی در element_geom() مربوط به استفاده از خطوط است. در یک نقش، مانند یک نمودار خطی، خط مستقیماً داده‌ها را نشان می‌دهد. در نقش دوم، یک خط به عنوان جداکننده بین دو واحد عمل می‌کند. به عنوان مثال، می‌توانید کشورها را به صورت چندضلعی نمایش دهید و خطی که رئوس را به هم متصل می‌کند، مکان‌هایی را که درون یک کشور هستند از مکان‌هایی که خارج از آن کشور هستند جدا می‌کند. این دو نقش در یک جفت linewidth و linetype و یک جفت borderwidth و bordertype نمایش داده می‌شوند.

ggplot(faithful, aes(waiting)) +
  geom_histogram(bins = 30, colour = "black") +
  geom_freqpoly(bins = 30) +
  theme(geom = element_geom(
    bordertype = "dashed",
    borderwidth = 0.2,
    linewidth = 2,
    linetype = "solid"
  ))
R
image 2 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

مقیاس‌ها و پالت‌ها

پالت‌های پیش‌فرض اکنون در تم‌ها تعریف می‌شوند. تنظیمات مربوطه با الگوی palette.{aesthetic}.{type} (که type می‌تواند discrete یا continuous باشد) مشخص می‌شوند:

ggplot(mpg, aes(displ, hwy, shape = drv, colour = cty)) +
  geom_point() +
  theme(
    palette.colour.continuous = c("chartreuse", "forestgreen"),
    palette.shape.discrete = c("triangle", "triangle open", "triangle down open")
  )
R
image 17 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

نحوه‌ کار این است که تمام مقیاس‌های پیش‌فرض مقدار palette = NULL دارند که هنگام ساخت نمودار با مقادیر تعریف شده در تم جایگزین می‌شود.

میانبرها

برای ساده‌سازی تعریف تم‌ها، توابع کمکی جدیدی معرفی شده‌اند:

این توابع با افزودن پیشوند مناسب، آرگومان‌ها را به theme() منتقل می‌کنند و کد را خواناتر می‌کنند. برای مثال، استفاده از theme_sub_legend(justification)  به theme(legend.justification) ترجمه می‌شود:

# روش قدیمی: طولانی و نامرتب
theme(
  panel.widths = unit(5, "cm"),
  axis.ticks.x = element_line(colour = "red"),
  axis.ticks.length.x = unit(5, "mm"),
  panel.background = element_rect(fill = NA),
  panel.spacing.x = unit(5, "mm")
)

# روش جدید: مختصر و منظم
theme_sub_axis_x(
  ticks = element_line(colour = "red"),
  ticks.length = unit(5, "mm")
) +
theme_sub_panel(
  widths = unit(5, "cm"),
  spacing.x = unit(5, "mm"),
  background = element_rect(fill = NA)
)
R

برای تعریف حاشیه‌ها، دو تابع جدید اضافه شده است:

  • margin_auto(): تعریف حاشیه‌ها به سبک CSS
    • margin_auto(1): هر چهار ضلع را به طور همزمان تنظیم می‌کند. این تابع به margin(t = 1, r = 1, b = 1, l = 1) بسط می‌یابد.
    • margin_auto(1, 2):  اضلاع افقی و عمودی را تنظیم می‌کند. این تابع به margin(t = 1, r = 2, b = 1, l = 2) بسط می‌یابد.
  • margin_part(): تعریف حاشیه‌های انتخابی با حفظ مقادیر پیش‌فرض
merge_element(
  margin_part(r = 20), # child
  margin_auto(10) # parent
)
#> [1] 10points 20points 10points 10points
R

تنظیمات جدید

عناصر ریشه جدید spacing و margins برای هماهنگ‌سازی فاصله‌ها در تم‌ها معرفی شده‌اند. عناصر دیگر از این مقادیر به ارث می‌برند. برای تنظیم نسبی مقادیر، می‌توان از rel() استفاده کرد. برای مثال، مقدار پیش‌فرض axis.ticks.length اکنون rel(0.5) است که باعث می‌شود تیک‌های محور y در نمودار زیر 0.5 سانتی‌متر باشند. اگر axis.ticks.length.x را روی rel(2) تنظیم کنیم، مقداری که از axis.ticks.length می‌آید را دو برابر می‌کند، نه مقدار spacing را.

p <- ggplot(penguins, aes(bill_dep, bill_len, colour = species)) +
  geom_point(na.rm = TRUE)

p + theme(
  spacing = unit(1, "cm"), 
  margins = margin_auto(1, unit = "cm"),
  axis.ticks.length.x = rel(2)
)
R
image 3 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

همچنین برای کنترل اندازه نمودارها، آرگومان‌های panel.widths و panel.heights اضافه شده‌اند که با ggsave(width, height) متفاوت هستند (این آرگومان‌ها فقط اندازه پنل‌ها را کنترل می‌کنند، نه کل نمودار). دو روش برای استفاده از این آرگومان‌ها وجود دارد:

  • یک بردار از واحدها بدهید: هر واحد به طور جداگانه روی یک پنل اعمال می‌شود و بردار برای تناسب با تعداد پنل‌ها اجرامی‌شود.
  • یک واحد یکسان بدهید: که مساحت کل پنل (شامل فواصل پنل‌ها و محورهای داخلی) را به آن اندازه تنظیم می‌کند.

طبیعتاً، اگر فقط یک پنل داشته باشید، این رویکردها یکسان هستند. اگر چندین پنل دارید و می‌خواهید اندازه پنل‌های جداگانه را یکسان کنید (برخلاف اندازه کل)، می‌توانید از آن استفاده کنید و از یک بردار واحد با طول ۲ استفاده کنید.

در نمودارهای زیر، می‌توانید متوجه شوید که پنل‌ها با وجود اینکه واحدها به مقدار یکسانی (۹ سانتی‌متر) جمع می‌شوند، عرض متفاوتی دارند. دلیل این امر این است که رویکرد «تک واحدی» شامل فواصل پنل‌ها نیز می‌شود، اما رویکرد دیگر شامل این موضوع نمی‌شود.

p1 <- p + facet_grid(~ island) +
  labs(title = "Separate units (per panel)") +
  # Using the new shortcut for panels
  theme_sub_panel(
    widths = unit(c(2, 3, 4), "cm"),
    heights = unit(3, "cm")
  )

p2 <- p + facet_grid(~ island) +
  labs(title = "Single unit (all panels)") +
  theme_sub_panel(
    widths = unit(9, "cm"),
    heights = unit(3, "cm")
  )

p1 / p2
R
image 4 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

برچسب‌گذاری

روش‌های جدیدی برای بازیابی برچسب متغیرها اضافه شده است. ggplot2 اکنون از ویژگی label (که در بسته‌هایی مانند gt، labelsd و Hmisc استفاده می‌شود) به عنوان برچسب پیش‌فرض متغیر استفاده می‌کند:

# فراخوانی دیتاست پیش‌فرض پنگوئن‌ها
df <- penguins

# تنظیم دستی لیبل‌ها
attr(df$species, "label") <- "Penguin Species"
attr(df$bill_dep, "label") <- "Bill depth (mm)"
attr(df$bill_len, "label") <- "Bill length (mm)"
attr(df$body_mass, "label") <- "Body mass (g)"

ggplot(df, aes(bill_dep, bill_len, colour = sqrt(body_mass))) +
  geom_point(na.rm = TRUE)
R
image 18 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

برای کار با دیکشنری‌ داده، آرگومان labs(dictionary) اضافه شده است. این آرگومان یک بردار نام‌دار از برچسب‌ها را می‌گیرد که می‌توان به راحتی آن را از یک دیکشنری با استفاده از setNames() یا dplyr::pull() تولید کرد.

dict <- tibble::tribble(
  ~var,    ~label,
  "species",  "Penguin Species",
  "bill_dep", "Bill depth (mm)",
  "bill_len", "Bill length (mm)",
  "body_mass", "Body mass (g)"
)

ggplot(penguins, aes(bill_dep, bill_len, colour = body_mass)) +
  geom_point(na.rm = TRUE) +
  # یا
  # labs(dictionary = dplyr::pull(dict, label, name = var))
  labs(dictionary = setNames(dict$label, dict$var))
R
Image 3

یکی از مزایای رویکردهای ویژگی‌های برچسب یا دیکشنری داده این است که به متغیرهای شما متصل است و نه در aesthtics (که در ggplot2 با aes نوشته می‌شود). این بدان معناست که می‌توانید به راحتی خود را برای یک نمودار متفاوت بازآرایی کنید، بدون اینکه مجبور باشید برچسب‌ها را صحیح با دقت مجدداً هدایت کنید.

last_plot() +
  aes(body_mass, bill_len, colour = species)
R
image 19 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

سلسله مراتب اولویت برچسب‌ها به ترتیب زیر است:

  1. عبارت در AES()
  2. ورودی در labs(dictionary)
  3. ویژگی label در ستون
  4. ورودی در labs(<aesthetic> = <label>)
  5. آرگومان scale_*(name)
  6. آرگومان guide_*(title)

این سلسله مراتب را می‌توانید در نمودار زیر ببینید. تابع در راهنمای محور ورودی را از Labs() استفاده کنید.

ggplot(penguins, aes(bill_dep, bill_len, colour = species)) +
  geom_point(na.rm = TRUE) +
  scale_colour_discrete(name = toupper) +
  guides(x = guide_axis(title = tools::toTitleCase)) +
  labs(
    y = \(x) paste0(x, " variable"),
    x = "the label for the x variable"
  )
R
image 5 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

برای مقیاس‌های گسسته، اگر breaks نامگذاری شده باشند، برچسب‌ها به طور پیش‌فرض از نام‌های breaks استفاده می‌کنند:

ggplot(penguins, aes(bill_dep, bill_len, colour = species)) +
  geom_point(na.rm = TRUE) +
  scale_colour_discrete(
    breaks = c(
      "Pygoscelis adeliae"     = "Adelie",
      "Pygoscelis papua"       = "Gentoo",
      "Pygoscelis antarcticus" = "Chinstrap"
    )
  )
R
image 6 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

مقیاس‌های گسسته

در این نسخه، انعطاف‌پذیری مقیاس‌های موقعیت گسسته افزایش یافته است. پیش از این، مقادیر گسسته همیشه به یک دنباله عدد صحیح نگاشت می‌شدند که از 1 شروع می‌شد و به تعداد سطوح می‌رسید. اکنون می‌توان از آرگومان palette برای تعریف نگاشت‌های سفارشی استفاده کرد:

ggplot(ToothGrowth, aes(interaction(dose, supp, sep = "\n"), len)) +
  geom_boxplot() +
  scale_x_discrete(
    palette = scales::pal_manual(c(1:3, 5:7))
  )
R

image 20 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

محدودیت‌های پیوسته مقیاس‌های گسسته اکنون با continuous.limits قابل کنترل هستند. همچنین قابلیت تعریف minor_breaks برای مقیاس‌های گسسته و پشتیبانی از محورهای ثانویه با dup_axis() اضافه شده است.

p1 <- ggplot(mpg, aes(class)) +
  geom_bar() +
  facet_wrap(~ drv, ncol = 1, scales = "free_x")

p2 <- p1 + scale_x_discrete(continuous.limits = c(1, 5))

(p1 + labs(title = "Free limits")) | 
(p2 + labs(title = "Fixed limits"))
R
image 7 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

مقیاس های موقعیت گسسته اکنون به محورهای ثانویه نیز دسترسی دارند. برخلاف مقیاس های پیوسته، مقیاس های گسسته از تبدیلات پشتیبانی نمی کنند. بنابراین به جای sec_axis()، توصیه می شود استفاده کنید dup_axis(). برای اجازه دادن به موقعیت های دلخواه برای dup_axis(breaks)، این می تواند مقادیر عددی یا یکی از سطوح گسسته را بگیرد. آنها واقعا برای نمایش دو مجموعه داده تراز شده با مقیاس های مختلف مفید نیستند، اما می توانند به عنوان حاشیه نویسی عمل کنند. به عنوان مثال، آنها می توانند برخی از آمارهای خلاصه در مورد گروه ها را نمایش دهند.

ggplot(mpg, aes(class, cty)) +
  geom_boxplot() +
  scale_x_discrete(
    sec.axis = dup_axis(
      name = "Counts",
      # You can use numeric input for breaks
      breaks = seq_len(length(unique(mpg$class))),
      # Watch out for the order of `table()` and your levels!
      labels = paste0("n = ", table(mpg$class))
    )
  )
R
image 21 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

موقعیت (position)

لایه ها از سه جزء تشکیل شده اند: آمار، ژئوم و موقعیت. آمار و ژئوم، aes خاص خود را دارند؛ مانند  weight و linewidth ، تنظیمات موقعیت این گونه نبودند. تنظیمات موقعیت اکنون می‌توانند پارامترهای اختصاصی داشته باشند. برای مثال در position_nudge()، پارامترهای nudge_x و nudge_y به عنوان پارامتر در دسترس هستند:

coal <- tibble::tribble(
  ~continent,  ~pct_1985, ~pct_2024,
  "Africa",        53.87, 24.68,
  "Asia",          32.60, 51.19,
  "Europe",        32.84, 12.91,
  "North America", 48.93, 13.79,
  "South America",  2.91,  3.31,
  "Oceania",       58.75, 39.26
) |>
  dplyr::mutate(pp_difference = pct_2024 - pct_1985)

ggplot(coal, aes(pp_difference, continent)) +
  geom_col() +
  geom_text(
    aes(nudge_x = sign(pp_difference) * 3, 
        label = pp_difference)
  ) +
  labs(x = "Change in electricity generated by coal (pp)")
R
image 22 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

ویژگی دیگر position_dodge() است که می‌توان برای مثال در کد زیر، ورزش‌هایی که آماری در هر جنس را ندارند، در نمودار در جای درستی قرار نگرفته‌اند. چرا که ggplot2 درکی از گروه‌های دیگر ندارد. جنسیت‌های مختلف یکی بالای خط و یکی زیر خط قرار دارد.

sports <- c("water polo", "swimming", "gymnastics", "field", "netball")
p <- ggridges::Aus_athletes |>
  dplyr::filter(sport %in% sports) |>
  ggplot(aes(height, sport, fill = sex)) +
  geom_boxplot(position = position_dodge(preserve = "single"))

p
R
image 9 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

برای حل این مساله الا می‌توانید در position_dodge(). از order استفاده کرد.

p + aes(order = sex)
R
Image 6

Facets

جهات

این تابع facet_wrap() دارای دو آرگومان است که طرح بندی را کنترل می کند: dir که می تواند "h" یا "v" باشد و as.table با می تواند TRUE یا FALSE باشد. با هم در مجموع ۴ گزینه طرح بندی را ارائه می‌دادند. در به روزرسانی جدید، آرگومان dir در facet_wrap() اکنون 8 حالت را با کدهای دو حرفی پشتیبانی می‌کند. گزینه های جدید همه کدهای دو حرفی هستند که از ترکیب t (بالا)، r (راست)، b (پایین) و l (چپ) استفاده می کنند. این ترکیب به شما می گوید که اولین سطح جنبه کجا خواهد بود. هر دو br و rb در پایین سمت راست با اولین جنبه شروع می شوند. سپس ترتیب جهت پر شدن را به شما می گوید، جایی که شروع با b از پایین به بالا پر می شود و با شروع با r از راست به چپ پر می شود.

p <- ggplot(mpg, aes(displ, hwy)) +
  geom_point()

p1 <- p + 
  facet_wrap(~ vctrs::vec_group_id(class), dir = "br") +
  labs(title = "dir = 'br'")

p2 <- p +
  facet_wrap(~ vctrs::vec_group_id(class), dir = "rb") +
  labs(title = "dir = 'rb'")

p1 | p2
R
image 10 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

۸ انتخاب پیش رو، به این ترتیب می‌باشد:

  • "lt": شروع از بالا-چپ، پر کردن از چپ به راست
  • "tl": شروع از بالا-چپ، پر کردن از بالا به پایین
  • "lb": شروع از پایین-چپ، پر کردن از چپ به راست
  • "bl": شروع از پایین-چپ، پر کردن از پایین به بالا
  • "rt": شروع از بالا-راست، پر کردن از راست به چپ
  • "tr": شروع از بالا-راست، پر کردن از بالا به پایین
  • "rb": شروع از پایین-راست، پر کردن از راست به چپ
  • "br": شروع از پایین-راست، پر کردن از پایین به بالا

فضای آزاد

آرگومان facet_grid(space) می تواند اطمینان حاصل کند که پنل‌ها متناسب با محدوده داده خود، فضا در اختیار بگیرند و اندازه پنل‌ها را متناسب با محدوده داده تنظیم می‌کند:

ggplot(penguins, aes(bill_dep, bill_len, colour = species)) +
  geom_point(na.rm = TRUE) +
  facet_wrap(~ island, scales = "free_x", space = "free_x")
R
Image 7

چیدمان لایه

آرگومان layer(layout) برای کنترل نحوه توزیع داده‌ها در پنل‌ها اضافه شده است. موارد زیر برای facet_wrap() و facet_grid()

  • layout = NULL: پیش‌فرض. استفاده از متغیرهای faceting
  • layout = “fixed” تکرار داده‌ها در تمام پنل‌ها
  • layout = <integer>: اختصاص داده‌ها به پنل خاص
  • layout = “fixed_cols”: تکرار داده‌ها در ستون
  • layout = “fixed_rows”: تکرار داده‌ها در ردیف
ggplot(penguins, aes(bill_dep, bill_len)) +
  # Repeat within every row
  geom_point(na.rm = TRUE, colour = "grey", layout = "fixed_rows") +
  # Use facetting variables (default)
  geom_point(na.rm = TRUE, layout = NULL) +
  # Pick particular panel
  annotate(
    "text", x = I(0.5), y = I(0.5),
    label = "Panel 6", layout = 6
  ) +
  facet_grid(island ~ species)
R
Image 8

به‌روزرسانی‌های ظاهری

Boxplot

امکان استایل‌دهی جداگانه اجزای boxplot (خط میانه، جعبه، خطوط (Wisker)و Staple) اضافه شده است:

ggplot(mpg, aes(class, hwy, colour = class)) +
  geom_boxplot(
    whisker.linetype = "dashed",
    box.colour = "black",
    median.linewidth = 2,
    staplewidth = 0.5, # show staple
    staple.colour = "grey50"
  ) +
  guides(colour = "none")
R
Image 9

آرگومان fatten منسوخ شده و جایگزین‌های median.linewidth و middle.linewidth معرفی شده‌اند.

ویولن و چارک‌ها

محاسبه چارک‌ها اکنون بر اساس داده‌های اصلی انجام می‌شود (نه داده‌های چگالی). به طور پیش فرض، چارک‌ها 25، 50 و 75 هستند و همیشه محاسبه می‌شوند. برای نمایش چارک‌ها، از آرگومان‌های quantile.colour، quantile.linetype و quantile.linewidth استفاده می‌شود. به طور پیش‌فرض quantile.linetype = 0 (بدون خط) است.

ggplot(mpg, aes(class, hwy, fill = class)) +
  geom_violin(
    quantiles = c(0.1, 0.9),
    quantile.linetype = 1
  ) +
  guides(fill = "none")
R
image 11 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

برچسب‌ها

geom_label() اکنون زیبایی‌شناسی‌های linetype و linewidth و آرگومان‌های border.colour و text.colour را پشتیبانی می‌کند.

ggplot(mtcars) +
  aes(
    wt, mpg,
    label = rownames(mtcars),
    colour = factor(cyl),
    linetype = factor(vs),
    linewidth = factor(am)
  ) +
  geom_label(text.colour = "black") +
  scale_linewidth_manual(values = c(0.3, 0.6))
R
image 12 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

مساحت و ریبون‌ها

geom_area() و geom_ribbon() اکنون از fill متغیر درون گروه پشتیبانی می‌کنند (نیاز به R 4.1.0+ دارد).

ggplot(economics, aes(date, unemploy)) +
  geom_area(aes(fill = uempmed))
R
image 13 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

آماره‌های جدید

manual

سیاری از پسوندهای ggplot بر اساس آمار هستند که به شما امکان می دهد محاسبات دلخواه را روی داده ها قبل از تحویل توابع ترسیم انجام دهید. هم ساخته شده تا stat_manual() امکان تعریف آماره سفارشی بدون نیاز به ساخت کلاس رسمی را فراهم می‌کند:

make_centroids <- function(df) {
  transform(
    df,
    xend = mean(x, na.rm = TRUE),
    yend = mean(y, na.rm = TRUE)
  )
}

make_hull <- function(df) {
  df <- df[complete.cases(df), , drop = FALSE]
  hull <- chull(df$x, df$y)
  df[hull, , drop = FALSE]
}

ggplot(penguins, aes(bill_len, bill_dep, colour = species)) + 
  geom_point(na.rm = TRUE) + 
  # As a stat, provide a geom
  stat_manual(
    geom = "segment", # function creates new xend/yend for segment
    fun = make_centroids,
    linewidth = 0.2,
    na.rm = TRUE
  ) +
  # As a geom, provide the stat
  geom_polygon(
    stat = "manual",
    fun = make_hull,
    fill = NA,
    linetype = "dotted"
  )
R
Image 10

Connection

stat_connect() امکان ایجاد اتصالات پله‌ای یا سفارشی بین نقاط را فراهم می‌کند:

eco <- economics |>
  dplyr::mutate(year = lubridate::year(date)) |>
  dplyr::summarise(
    min = min(unemploy),
    max = max(unemploy),
    mid = median(unemploy),
    .by = year
  )

ggplot(eco, aes(year, y = mid, ymin = min, ymax = max)) +
  geom_line(stat = "connect") +
  geom_ribbon(stat = "connect", alpha = 0.4)
R
image 14 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

همچنین می‌توانید از یک ماتریس عددی 2 ستونی برای ترسیم انواع دیگر اتصالات استفاده کنید. به عنوان مثال اگر از plogis() برای ایجاد یک انتقال لجستیک، می توانیم اتصالات مانندی ‌نمودار Bump ایجاد کنید.

x <- seq(0, 1, length.out = 20)[-1]
smooth <- cbind(x, scales::rescale(plogis(x, location = 0.5, scale = 0.1)))
zigzag <- cbind(c(0.4, 0.6, 1), c(0.75, 0.25, 1))

ggplot(head(eco, 10), aes(year, y = mid)) +
  geom_point() +
  stat_connect(aes(colour = "smooth"), connection = smooth) +
  stat_connect(aes(colour = "zigzag"), connection = zigzag)
R
image 15 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

معکوس‌سازی مختصات

تبدیل کردن معکوس که پیش‌از این با محدودیت‌هایی روبرو بوده، یا برای مثال در مقیاس‌های گسسته پشتیبانی نمی‌شده الان با reverse امکان‌پذیر شده‌است. آرگومان reverse برای سیستم‌های مختصات (coords) اضافه شده است که معکوس‌سازی محورها را ساده‌تر می‌کند. این آرگومان می‌تواند  "none"، "x"، "y" یا "xy" باشد. در coord_radial()، این آرگومان جایگزین direction شده است.

world <- sf::st_as_sf(maps::map('world', plot = FALSE, fill = TRUE))

ggplot(world) +
  geom_sf() +
  coord_sf(reverse = "y")
R
image 16 | به‌روزرسانی بسته ggplot2 +تغییرات 4.0

امکانات برای افزونه‌ها

لایه‌ها

تابع gg_par() برای تبدیل تنظیمات ggplot2 به تنظیمات grid معرفی شده است:

gg_par(lwd = 5)
#> $lwd
#> [1] 14.22638
grid::convertUnit(unit(5, "mm"), "pt")
#> [1] 14.2263779527559points
R

make_constructor() تولید سازنده‌های خودکار برای کلاس‌های Geom* و Stat* را ساده می‌کند.

تم‌ها

complete_theme() برای تکمیل و اعتبارسنجی تم‌ها معرفی شده است. عناصر تم جدید element_point و element_polygon برای استفاده در افزونه‌ها اضافه شده‌اند. این موارد در تنظیمات پایه ggplot2 استفاده نمی‌شوند.

# Let's say your package 'my_pkg' registers custom point/polygon elements
register_theme_elements(
  my_pkg_point = element_point(colour = "red"),
  my_pkg_polygon = element_polygon(fill = NA),
  element_tree = list(
    my_pkg_point = el_def(element_point, inherit = "point"),
    my_pkg_polygon = el_def(element_polygon, inherit = "polygon")
  )
)

# Which should inherit from the root point/polygon theme elements
my_theme <- theme(
  point = element_point(shape = 17),
  polygon = element_polygon(linetype = "dotted")
) |>
  complete_theme()

# Rendering your elements
pts <- calc_element("my_pkg_point", my_theme) |>
  element_grob(
    x = c(0.2, 0.5, 0.8),
    y = c(0.8, 0.2, 0.5)
  )
poly <- calc_element("my_pkg_polygon", my_theme) |>
  element_grob(
    x = c(0.1, 0.5, 0.9),
    y = c(0.9, 0.1, 0.5)
  )

# Drawing the elements
grid::grid.newpage()
grid::grid.draw(pts)
grid::grid.draw(poly)
R
Image 12

  1. این نوشته، ترجمه‌ای است آزاد از معرفی این نسخه در وبلاگ Tidyverse. کدها و نمودارها از همین لینک برداشته شده است. ↩︎

دیدگاه‌ها

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors