الهدف من هذا المستودع هو تتبع بعض الحيل ggplot2 الأنيقة التي تعلمتها. هذا يفترض أنك تعرفت على أساسيات GGPLOT2 ويمكنك بناء بعض المؤامرات اللطيفة الخاصة بك. إذا لم يكن كذلك ، يرجى الاطلاع على الكتاب في ليجر.
أنا لا أتكيف بشكل لا يصدق في مخططات التنضيد المجيدة ومواضيع وألوان ألوان بخبرة ، لذلك عليك أن تسامحني. مجموعة بيانات mpg
متعددة الاستخدامات للغاية للتخطيط ، لذلك سترى الكثير من ذلك كما تقرأ. حزم التمديد رائعة ، وقد انخرطت بنفسي ، لكنني سأحاول أن أقصر نفسي على حيل الفانيليا GGPLOT2 هنا.
في الوقت الحالي ، سيكون هذا في الغالب حقيبة من الحيل فقط ، لكنني قد أقرر لاحقًا وضعها في مجموعات منفصلة في ملفات أخرى.
عن طريق تحميل المكتبة وتحديد موضوع التخطيط. الخدعة الأولى هنا هي استخدام theme_set()
لتعيين سمة لجميع المخططات الخاصة بك في جميع أنحاء المستند. إذا وجدت نفسك تضع موضوعًا مطوّلاً للغاية لكل قطعة ، فإليك المكان الذي تقوم فيه بتعيين جميع الإعدادات الشائعة. ثم لا تكتب أبدًا رواية عن عناصر الموضوع مرة أخرى 1 !
library( ggplot2 )
library( scales )
theme_set(
# Pick a starting theme
theme_gray() +
# Add your favourite elements
theme(
axis.line = element_line(),
panel.background = element_rect( fill = " white " ),
panel.grid.major = element_line( " grey95 " , linewidth = 0.25 ),
legend.key = element_rect( fill = NA )
)
)
وثائق ?aes
لا تخبرك بذلك ، ولكن يمكنك لصق وسيطة mapping
في GGPLOT2. ماذا يعني ذلك؟ حسنًا ، هذا يعني أنه يمكنك إنشاء وسيطة mapping
أثناء التنقل !!!
. هذا أمر رائع إذا كنت بحاجة إلى إعادة تدوير جماليات كل مرة.
my_mapping <- aes( x = foo , y = bar )
aes( colour = qux , !!! my_mapping )
# > Aesthetic mapping:
# > * `x` -> `foo`
# > * `y` -> `bar`
# > * `colour` -> `qux`
الاستخدام المفضل لدي لهذا هو جعل لون fill
يتطابق مع colour
، ولكن أخف قليلاً 2 . سنستخدم نظام التقييم المتأخر لهذا الغرض ، after_scale()
في هذه الحالة ، والذي سترى أكثر في القسم بعد هذا القسم. سأكرر هذه الخدعة عدة مرات خلال هذا المستند.
my_fill <- aes( fill = after_scale(alpha( colour , 0.3 )))
ggplot( mpg , aes( displ , hwy )) +
geom_point(aes( colour = factor ( cyl ), !!! my_fill ), shape = 21 )
قد تجد نفسك في موقف يطلب منك فيه صنع خريطة حرارية لعدد صغير من المتغيرات. عادةً ما يتم تشغيل المقاييس المتسلسلة من الضوء إلى الظلام أو العكس ، مما يجعل النص بلونًا واحدًا يصعب قراءته. يمكننا وضع طريقة لكتابة النص تلقائيًا باللون الأبيض على خلفية مظلمة ، والأسود على خلفية خفيفة. تنظر الدالة أدناه
contrast <- function ( colour ) {
out <- rep( " black " , length( colour ))
light <- farver :: get_channel( colour , " l " , space = " hcl " )
out [ light < 50 ] <- " white "
out
}
الآن ، يمكننا أن نجعل جمالية ليتم تقسيمها في حجة mapping
للطبقة عند الطلب.
autocontrast <- aes( colour = after_scale(contrast( fill )))
أخيرًا ، يمكننا اختبار تناقض التباين التلقائي. قد تلاحظ أنه يتكيف مع المقياس ، لذلك لن تحتاج إلى القيام بمجموعة من التنسيق الشرطي لهذا الغرض.
cors <- cor( mtcars )
# Melt matrix
df <- data.frame (
col = colnames( cors )[as.vector(col( cors ))],
row = rownames( cors )[as.vector(row( cors ))],
value = as.vector( cors )
)
# Basic plot
p <- ggplot( df , aes( row , col , fill = value )) +
geom_raster() +
geom_text(aes( label = round( value , 2 ), !!! autocontrast )) +
coord_equal()
p + scale_fill_viridis_c( direction = 1 )
p + scale_fill_viridis_c( direction = - 1 )
هناك بعض الامتدادات التي توفر إصدارات نصف الجيوم من الأشياء. من بين الأشخاص الذين أعرفهم ، تقدم Gghalves و The See Package بعض الجزور.
فيما يلي كيفية إساءة استخدام نظام التقييم المتأخر لصنعه. يمكن أن يكون هذا مفيدًا إذا لم تكن على استعداد لتولي تبعية إضافية لهذه الميزة فقط.
الحالة السهلة هي boxplot. يمكنك إما تعيين xmin
أو xmax
على after_scale(x)
للحفاظ على الأجزاء اليمنى واليسرى من boxplot على التوالي. هذا لا يزال يعمل بشكل جيد مع position = "dodge"
.
# A basic plot to reuse for examples
p <- ggplot( mpg , aes( class , displ , colour = class , !!! my_fill )) +
guides( colour = " none " , fill = " none " ) +
labs( y = " Engine Displacement [L] " , x = " Type of car " )
p + geom_boxplot(aes( xmin = after_scale( x )))
نفس الشيء الذي يعمل مع boxplots ، يعمل أيضا مع errorbars.
p + geom_errorbar(
stat = " summary " ,
fun.data = mean_se ,
aes( xmin = after_scale( x ))
)
يمكننا مرة أخرى أن نفعل نفس الشيء بالنسبة لمؤامرات الكمان ، لكن الطبقة تشكو من عدم معرفة جمالية xmin
. لا يستخدم هذا الجمالية ، ولكن فقط بعد إعداد البيانات ، لذلك لا يُقصد منه أن يكون جمالية يمكن للمستخدم الوصول إليها. يمكننا إسكات التحذير من خلال تحديث الافتراضي لـ xmin
إلى NULL
، مما يعني أنه لن يشكو ، ولكن أيضًا لا يستخدمه إذا كان غائبًا.
update_geom_defaults( " violin " , list ( xmin = NULL ))
p + geom_violin(aes( xmin = after_scale( x )))
لم يتم تركه كتمرين للقارئ هذه المرة ، لكنني أردت فقط أن أوضح كيف ستعمل إذا كنت ستجمع بين نصفين وتريد تعويضهما قليلاً عن بعضهما البعض. سنقوم بإساءة استخدام أشرطة الخطأ لتكون بمثابة المواد الغذائية الأساسية لـ Boxplots.
# A small nudge offset
offset <- 0.025
# We can pre-specify the mappings if we plan on recycling some
right_nudge <- aes(
xmin = after_scale( x ),
x = stage( class , after_stat = x + offset )
)
left_nudge <- aes(
xmax = after_scale( x ),
x = stage( class , after_stat = x - offset )
)
# Combining
p +
geom_violin( right_nudge ) +
geom_boxplot( left_nudge ) +
geom_errorbar( left_nudge , stat = " boxplot " , width = 0.3 )
دعنا نقول أن لديك حدس لون أفضل مني ، وثلاثة ألوان لا تكفي لاحتياجات لوحة الألوان المتباينة. نقطة الألم هي أنه من الصعب الحصول على نقطة الوسط بشكل صحيح إذا لم تكن حدودك تتركز حولها تمامًا. أدخل حجة rescaler
في League with scales::rescale_mid()
.
my_palette <- c( " dodgerblue " , " deepskyblue " , " white " , " hotpink " , " deeppink " )
p <- ggplot( mpg , aes( displ , hwy , colour = cty - mean( cty ))) +
geom_point() +
labs(
x = " Engine displacement [L] " ,
y = " Highway miles per gallon " ,
colour = " Centered n value "
)
p +
scale_colour_gradientn(
colours = my_palette ,
rescaler = ~ rescale_mid( .x , mid = 0 )
)
البديل هو ببساطة مركز الحدود على x. يمكننا القيام بذلك من خلال توفير وظيفة لحدود المقياس.
p +
scale_colour_gradientn(
colours = my_palette ,
limits = ~ c( - 1 , 1 ) * max(abs( .x ))
)
يمكنك تسمية النقاط باستخدام geom_text()
، ولكن المشكلة المحتملة هي أن النص والنقاط يتداخل.
set.seed( 0 )
df <- USArrests [sample(nrow( USArrests ), 5 ), ]
df $ state <- rownames( df )
q <- ggplot( df , aes( Murder , Rape , label = state )) +
geom_point()
q + geom_text()
هناك العديد من الحلول النموذجية لهذه المشكلة ، وكلها تأتي مع عيوب:
nudge_x
و nudge_y
. المشكلة هنا هي أن هذه هي المحددة في وحدات البيانات ، وبالتالي فإن التباعد لا يمكن التنبؤ به ، ولا توجد طريقة لوجودها تعتمد على المواقع الأصلية.hjust
و vjust
. يسمح لك بالاعتماد على المواقع الأصلية ، ولكن لا تحتوي على إزاحة طبيعية.فيما يلي الخيارات 2 و 3 في العمل:
q + geom_text( nudge_x = 1 , nudge_y = 1 )
q + geom_text(aes(
hjust = Murder > mean( Murder ),
vjust = Rape > mean( Rape )
))
قد تفكر: "يمكنني فقط ضرب المبررات للحصول على إزاحة أوسع" ، وستكون على حق. ومع ذلك ، لأن التبرير يعتمد على حجم النص الذي قد تحصل عليه غير متكافئ. لاحظ في المؤامرة أدناه أن "North Dakota" يتم تعويضه أيضًا في اتجاه Y و "Rhode Island" في الاتجاه X.
q + geom_text(aes(
label = gsub( " North Dakota " , " North n Dakota " , state ),
hjust = (( Murder > mean( Murder )) - 0.5 ) * 1.5 + 0.5 ,
vjust = (( Rape > mean( Rape )) - 0.5 ) * 3 + 0.5
))
الشيء الجميل من geom_label()
هو أنه يمكنك إيقاف تشغيل مربع الملصقات والاحتفاظ بالنص. وبهذه الطريقة ، يمكنك الاستمرار في استخدام أشياء مفيدة أخرى ، مثل إعداد label.padding
q + geom_label(
aes(
label = gsub( " " , " n " , state ),
hjust = Murder > mean( Murder ),
vjust = Rape > mean( Rape )
),
label.padding = unit( 5 , " pt " ),
label.size = NA , fill = NA
)
كان هذا بمثابة نصيحة حول وضع علامات الوجه في الألواح ، والتي كانت معقدة. مع GGPLOT2 3.5.0 ، لم يعد عليك أن تملأ مع وضع مواقف لا حصر لها والتبديل معلمات hjust
أو vjust
. يمكنك الآن استخدام x = I(0.95), y = I(0.95)
لوضع النص في الزاوية اليمنى العلوي. افتح التفاصيل لرؤية النصيحة القديمة.
يعد وضع التعليقات التوضيحية النصية على قطع الوجه أمرًا مؤلمًا ، لأن الحدود يمكن أن تختلف على أساس لكل لوحة ، لذلك من الصعب جدًا العثور على الموضع الصحيح. التمديد الذي يستكشف تخفيف هذا الألم هو امتداد Tagger ، ولكن يمكننا القيام بشيء مماثل في الفانيليا GGPLOT2.
لحسن الحظ ، هناك ميكانيكي في محاور موضع GGPLOT2 التي تفسرنا -Inf
و Inf
على أنها الحد الأدنى والحد الأقصى للمقياس على التوالي 3 . يمكنك استغلال هذا عن طريق اختيار x = Inf, y = Inf
لوضع الملصقات في الزاوية. يمكنك أيضًا استخدام -Inf
بدلاً من Inf
لوضعها في الأسفل بدلاً من الأعلى أو اليسار بدلاً من اليمين.
نحن بحاجة إلى مطابقة الحجج hjust
/ vjust
إلى جانب المؤامرة. بالنسبة لـ x/y = Inf
، يجب أن تكون hjust/vjust = 1
، وبالنسبة x/y = -Inf
يجب أن تكون hjust/vjust = 0
.
p + facet_wrap( ~ class , scales = " free " ) +
geom_text(
# We only need 1 row per facet, so we deduplicate the facetting variable
data = ~ subset( .x , ! duplicated( class )),
aes( x = Inf , y = Inf , label = LETTERS [seq_along( class )]),
hjust = 1 , vjust = 1 ,
colour = " black "
)
لسوء الحظ ، يضع هذا النص مباشرة على حدود اللوحة ، والتي قد تسيء إلى إحساسنا بالجمال. يمكننا الحصول على مربو طفيف باستخدام geom_label()
، والذي يتيح لنا التحكم بشكل أكثر دقة في التباعد بين النص وحدود اللوحة عن طريق تعيين وسيطة label.padding
.
علاوة على ذلك ، يمكننا استخدام label.size = NA, fill = NA
لإخفاء جزء مربع النص من geom. لأغراض التوضيح ، نضع الآن العلامة في أعلى اليسار بدلاً من أعلى اليمين.
p + facet_wrap( ~ class , scales = " free " ) +
geom_label(
data = ~ subset( .x , ! duplicated( class )),
aes( x = - Inf , y = Inf , label = LETTERS [seq_along( class )]),
hjust = 0 , vjust = 1 , label.size = NA , fill = NA ,
label.padding = unit( 5 , " pt " ),
colour = " black "
)
دعنا نقول أننا مكلفون بصنع مجموعة من المؤامرات المماثلة ، مع مجموعات بيانات وأعمدة مختلفة. على سبيل المثال ، قد نرغب في إنشاء سلسلة من Barplots 4 مع بعض المجموعات المسبقة المحددة: نود أن تلمس الحانات المحور X وليس رسم خطوط الشبكات الرأسية.
إحدى الطرق المعروفة لصنع مجموعة من المؤامرات المماثلة هي لف بناء المؤامرة في وظيفة. وبهذه الطريقة ، يمكنك استخدام تشفير جميع الإعدادات المسبقة التي تريدها في وظيفتك.
أنا قد لا تعرف ، هناك طرق مختلفة للبرمجة مع وظيفة aes()
، واستخدام {{ }}
(مجعد-كورلي) هو واحد من أكثر الطرق مرونة 5 .
barplot_fun <- function ( data , x ) {
ggplot( data , aes( x = {{ x }})) +
geom_bar( width = 0.618 ) +
scale_y_continuous( expand = c( 0 , 0 , 0.05 , 0 )) +
theme( panel.grid.major.x = element_blank())
}
barplot_fun( mpg , class )
عيب واحد من هذا النهج هو أن تقفل أي جماليات في حجج الوظيفة. للتجول في هذا ، هناك طريقة أبسط هي ببساطة المرور ...
مباشرة إلى aes()
.
barplot_fun <- function ( data , ... ) {
ggplot( data , aes( ... )) +
geom_bar( width = 0.618 ) +
scale_y_continuous( expand = c( 0 , 0 , 0.1 , 0 )) +
theme( panel.grid.major.x = element_blank())
}
barplot_fun( mpg , class , colour = factor ( cyl ), !!! my_fill )
طريقة أخرى للقيام بشيء مشابه جدًا ، هي استخدام مؤامرة "الهياكل العظمية". الفكرة وراء الهيكل العظمي هي أنه يمكنك بناء مؤامرة ، مع أو بدون أي وسيطة data
، وإضافة التفاصيل لاحقًا. ثم ، عندما تريد بالفعل إنشاء مؤامرة ، يمكنك استخدام %+%
لملء أو استبدال مجموعة البيانات ، و + aes(...)
لتعيين الجماليات ذات الصلة.
barplot_skelly <- ggplot() +
geom_bar( width = 0.618 ) +
scale_y_continuous( expand = c( 0 , 0 , 0.1 , 0 )) +
theme( panel.grid.major.x = element_blank())
my_plot <- barplot_skelly % + % mpg +
aes( class , colour = factor ( cyl ), !!! my_fill )
my_plot
أحد الأشياء الأنيقة في هذه الهياكل العظمية هو أنه حتى عندما تملأ بالفعل data
mapping
الخرائط ، يمكنك استبدالها مرارًا وتكرارًا.
my_plot % + % mtcars +
aes( factor ( carb ), colour = factor ( cyl ), !!! my_fill )
الفكرة هنا هي عدم الهيكل العظمي للمؤامرة بأكملها ، ولكن مجرد مجموعة من الأجزاء التي أعيد استخدامها بشكل متكرر. على سبيل المثال ، قد نرغب في تسمية barplot لدينا ، وحزم كل الأشياء التي تشكل barplot المسمى. الحيلة لهذا هو عدم إضافة هذه المكونات مع +
، ولكن ببساطة وضعها في list()
. يمكنك بعد ذلك +
قائمتك مع مكالمة المؤامرة الرئيسية.
labelled_bars <- list (
geom_bar( my_fill , width = 0.618 ),
geom_text(
stat = " count " ,
aes( y = after_stat( count ),
label = after_stat( count ),
fill = NULL , colour = NULL ),
vjust = - 1 , show.legend = FALSE
),
scale_y_continuous( expand = c( 0 , 0 , 0.1 , 0 )),
theme( panel.grid.major.x = element_blank())
)
ggplot( mpg , aes( class , colour = factor ( cyl ))) +
labelled_bars +
ggtitle( " The `mpg` dataset " )
ggplot( mtcars , aes( factor ( carb ), colour = factor ( cyl ))) +
labelled_bars +
ggtitle( " The `mtcars` dataset " )
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.3.2 (2023-10-31 ucrt)
#> os Windows 11 x64 (build 22631)
#> system x86_64, mingw32
#> ui RTerm
#> language (EN)
#> collate English_Netherlands.utf8
#> ctype English_Netherlands.utf8
#> tz Europe/Amsterdam
#> date 2024-02-27
#> pandoc 3.1.1
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> cli 3.6.2 2023-12-11 [] CRAN (R 4.3.2)
#> colorspace 2.1-0 2023-01-23 [] CRAN (R 4.3.2)
#> digest 0.6.34 2024-01-11 [] CRAN (R 4.3.2)
#> dplyr 1.1.4 2023-11-17 [] CRAN (R 4.3.2)
#> evaluate 0.23 2023-11-01 [] CRAN (R 4.3.2)
#> fansi 1.0.6 2023-12-08 [] CRAN (R 4.3.2)
#> farver 2.1.1 2022-07-06 [] CRAN (R 4.3.2)
#> fastmap 1.1.1 2023-02-24 [] CRAN (R 4.3.2)
#> generics 0.1.3 2022-07-05 [] CRAN (R 4.3.2)
#> ggplot2 * 3.5.0.9000 2024-02-27 [] local
#> glue 1.7.0 2024-01-09 [] CRAN (R 4.3.2)
#> gtable 0.3.4 2023-08-21 [] CRAN (R 4.3.2)
#> highr 0.10 2022-12-22 [] CRAN (R 4.3.2)
#> htmltools 0.5.7 2023-11-03 [] CRAN (R 4.3.2)
#> knitr 1.45 2023-10-30 [] CRAN (R 4.3.2)
#> labeling 0.4.3 2023-08-29 [] CRAN (R 4.3.1)
#> lifecycle 1.0.4 2023-11-07 [] CRAN (R 4.3.2)
#> magrittr 2.0.3 2022-03-30 [] CRAN (R 4.3.2)
#> munsell 0.5.0 2018-06-12 [] CRAN (R 4.3.2)
#> pillar 1.9.0 2023-03-22 [] CRAN (R 4.3.2)
#> pkgconfig 2.0.3 2019-09-22 [] CRAN (R 4.3.2)
#> R6 2.5.1 2021-08-19 [] CRAN (R 4.3.2)
#> ragg 1.2.7 2023-12-11 [] CRAN (R 4.3.2)
#> rlang 1.1.3 2024-01-10 [] CRAN (R 4.3.2)
#> rmarkdown 2.25 2023-09-18 [] CRAN (R 4.3.2)
#> rstudioapi 0.15.0 2023-07-07 [] CRAN (R 4.3.2)
#> scales * 1.3.0 2023-11-28 [] CRAN (R 4.3.2)
#> sessioninfo 1.2.2 2021-12-06 [] CRAN (R 4.3.2)
#> systemfonts 1.0.5 2023-10-09 [] CRAN (R 4.3.2)
#> textshaping 0.3.7 2023-10-09 [] CRAN (R 4.3.2)
#> tibble 3.2.1 2023-03-20 [] CRAN (R 4.3.2)
#> tidyselect 1.2.0 2022-10-10 [] CRAN (R 4.3.2)
#> utf8 1.2.4 2023-10-22 [] CRAN (R 4.3.2)
#> vctrs 0.6.5 2023-12-01 [] CRAN (R 4.3.2)
#> viridisLite 0.4.2 2023-05-02 [] CRAN (R 4.3.2)
#> withr 3.0.0 2024-01-16 [] CRAN (R 4.3.2)
#> xfun 0.41 2023-11-01 [] CRAN (R 4.3.2)
#> yaml 2.3.8 2023-12-11 [] CRAN (R 4.3.2)
#>
#>
#> ──────────────────────────────────────────────────────────────────────────────
حسنًا ، تحتاج إلى القيام بذلك مرة واحدة في بداية المستند الخاص بك. ولكن بعد ذلك أبدا مرة أخرى! إلا في وثيقتك التالية. فقط اكتب script plot_defaults.R
source()
من المستند الخاص بك. نسخ هذا البرنامج النصي لكل مشروع. ثم ، حقا ، أبدا مرة أخرى: القلب :. ↩
هذه كذبة. في الواقع ، أستخدم aes(colour = after_scale(colorspace::darken(fill, 0.3)))
بدلاً من تفتيح التعبئة. لم أكن أرغب في الحصول على هذا ReadMe اعتماد على {colorpace}. ↩
إلا إذا كنت تخبر ذاتيًا مخططاتك عن طريق ضبط oob = scales::oob_censor_any
في المقياس على سبيل المثال. ↩
في روحك من النفوس ، هل تريد حقًا أن تصنع مجموعة من barplots؟ ↩
البديل هو استخدام ضمير .data
، والذي يمكن أن يكون .data$var
إذا كنت ترغب في قفل هذا العمود مقدمًا ، أو .data[[var]]
عندما يتم تمرير var
كحرف. ↩
كان هذا البت يسمى في الأصل "الهيكل العظمي الجزئي" ، ولكن كقبة قبرية هي جزء من الهيكل العظمي ، بدا هذا العنوان أكثر إثارة. ↩