به نام خدا


نمایش داده
(Data Visualization)
چرا ggplot2 ؟


چرا از ggplot2 برای آموزش و شروع کار استفاده می‌کنیم و از خود ابزار نمودارسازی R استفاده نمی‌کنیم ؟
  • در ggplot2 شما تنها مواردی را انتخاب می‌کنید که برای تجسم‌سازی دادهِ شما ضروری می‌باشد ، در حالی که برای کشیدن نمودار و تجسم‌سازی با استفاده از خود R ، باید جز به جز نمودار خود را بسازید که کار را برای افراد مبتدی سخت می‌کند.
  • ggplot2 انعطاف‌پذیرتر و دارای تم‌ها و طرح های متنوع و بیشتر می‌باشد.
  • ggplot2 از Grammar of Graphics پیروی می‌کند.

Grammar of Graphics چیست ؟


به طور خلاصه :
ابزاری که به ما کمک می‌کند تا با مشخص کردن بخش های اساسی نمودار به طور مستقل از هم و ترکیب کردن آن‌ها به صورت زنجیری نمودار‌های مورد نظر خود را رسم کنیم.

بخش های اساسی شامل :
  • داده (Data)
  • نگاشت Aesthetic ها
  • اشیا هندسی (Geomteric Objects)
  • تبدیل‌های آماری (Statistical Transformations)
  • مقیاس ها
  • دستگاه‌های مختصات (Coordinate Systems)
  • تنظیم موقعیت (Position Adjustments)
  • Faceting

(توصیه می‌کنم برای آشنایی بیشتر با اساس این موضوع مقاله زیر را از Hadley Wickham بخوانید)
نصب و فراخوانی ggplot2


توسط دستور
In [ ]:
install.packages("ggplot2")
این پکیج را نصب می‌کنیم. پس از نصب، این پکیج را توسط دستور
In [1]:
library(ggplot2)
فراخوانی می‌کنیم.

در این بخش از دیتافریم هایی که در خود ggplot2 می‌باشند استفاده می‌کنیم.
دیتافریم mpg : مشاهداتِ جمع‌آوری شده از اطلاعات 38 مدل خودرو .
برای دیدن اطلاعات این دیتافریم و توضیح هر یک از متغیر‌ها کافیست مستندات آن را مطالعه کنید.
In [2]:
?mpg



آشنایی با ggplot2


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

نمودار مقدار مسافت طی‌شده با یک گالون سوخت (hwy) نسبت به اندازه موتور خودرو (displ) را رسم کنیم :
In [3]:
## plot size
library(repr)
options(repr.plot.width=5.5, repr.plot.height=4.5)
##

ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy))
در ggplot2 شما با فراخوانی تابع ()ggplot رسم نمودار را شروع می‌کنید.
این تابع یک دستگاه مختصاتی ایجاد می‌کند که می‌توانید لایه هایی به آن اضافه کنید. اولین پارامتر این تابع ، مجموعه‌داده (Dataset) می‌باشد.
تابع ()ggplot به تنهایی هیچ خروجی بصری‌ای ندارد و ما نیازمند اشیا هندسی (Geometric Objects به طور مخفف geom) هستیم.
در این‌جا تابع ()geom_point به نمودار ما لایه‌ای از نقاط را اضافه می‌کند که منجر به تولید یک نمودار پراکنش(Scatterplot) می‌شود.
ggplot2 دارای توابع geom متفاوتی می‌باشد که هر یک ، لایه‌ای خاص به نمودار اضافه می‌کند.
هر یک از این توابع یک نگاشت(mapping) به عنوان پارامتر دریافت می‌کنند ، که نشان‌دهنده این است که متغیر‌های مجموعه‌دادهِ ما چگونه به نمودار نگاشت شوند.
پارامتر mapping همیشه به همراه تابع ()aes می‌آید. این تابع مشخص‌کننده نقش هر متغیر می‌باشد. در اینجا مشخص می‌کند که کدام یک از متغیر‌ها از دادهِ ما به عنوان محورهای x و y قرار گیرند.






Aesthetics :


aes مخفف aesthetics می‌باشد که در ggplot2 به معنی ویژگی بصری اشیا در نمودار ، می‌باشد. برخی از این aesthetic ها شامل :
  • Position
  • Color
  • Shape
  • Linetype
  • etc.

با نگاشت aesthetic ها به متغیرها می‌توانیم اطلاعات بیشتری درباره‌ی داده را در نمودار قرار دهیم. برای این کار کافیست در داخل ()aes نام aesthetic مورد نظر را به نام متغیر مورد‌نظر پیوند دهیم.
In [4]:
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy, color = class))
که نقاط را بر اساس نوع ماشین‌ها رنگ می‌کند.
تابع ()aes هر یک از نگاشت‌های aesthetic هر لایه را به پارامتر mapping آن لایه می‌فرستد.
با هربار نگاشت کردن aesthetic ها ، ggplot2 یک مقیاس برای آن انتخاب می‌کند و با ساخت توضیحی (legend) نگاشتِ بین مقادیر آن متغیر و سطوح آن aesthetic را شرح می‌دهد.
در مثال بالا میتوانیم این legend را در کنار نمودار ببینیم.

توجه کنیم که x و y نیز aesthetic هستند. ( زیرا مختصات x و y نیز از ویژگی‌های بصری نقاط هستند.) اما برای x و y توضیحی ساخته نمی‌شود زیرا برای آن‌ها محور‌های مختصات را داریم.

aesthetic ها می‌توانند مقادیری ثابت نیز داشته باشند. در این حالت اطلاعات اضافه‌ای به همراه نمودار انتقال داده نمی‌شود و فقط شکل ظاهری نمودار تغییر می‌کند.
In [5]:
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy), color = "red")



Geometric Objects :


geom ها نشانه هایی هستند که ما بر روی نمودار می‌گذاریم. مثال :
  • نقاط
  • خطوط
  • و ...
ما معمولا هر نمودار را بر حسب geom ای که استفاده می‌کند می‌شناسیم. به عنوان مثال : نمودار میله‌ای از geom میله‌ای استفاده می‌کند. (()geom_bar)
ما می‌توانیم از geom های متفاوت برای نمودار کشیدن داده استفاده کنیم.

همان مثال بخش قبل ، اما این بار خطی را به داده‌ها جفت می‌کنیم.
In [7]:
ggplot(data = mpg) + 
  geom_smooth(mapping = aes(x = displ, y = hwy))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
هریک از geom ها از تعدادی از aesthetic ها را برای پارامتر mapping خود پشتیبانی می‌کنند.
در جدول زیر پرکاربردترین geom ها و aesthetic هایی که پشتیبانی می‌کنند آورده شده است :


(عکس بالا از کتاب R in Action گرفته شده است.)

همانطور که در ابتدا گفتیم ggplot2 به صورت زنجیری توابع را با هم ترکیب می‌کند. ما نیز می‌توانیم از چند تابع geom برای رسم نمودار خود استفاده کنیم.

در مثال زیر از دو geom استفاده می‌کنیم و رنگ نقاط ، رنگ خطوط و نوع خط را برا اساس متغیر drv مشخص می‌کنیم.
In [8]:
ggplot(data = mpg) + 
  geom_point(mapping = aes(x = displ, y = hwy , color = drv)) +
  geom_smooth(mapping = aes(x = displ, y = hwy,color = drv, linetype = drv))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
اما به نظر شما قطعه کد بالا چه مشکلی دارد ؟
تکرار زیادی را در کد بالا انجام انجام داده‌ایم.

چگونه از این تکرار جلوگیری کنیم ؟ اگر به پارامتر های تابع ()ggplot دقت کرده باشید حتما دیده‌اید که این تابع نیز پارامتر نگاشت(mapping) را دارا می‌باشد.
این پارامتر در تابع ()ggplot به عنوان پارامتر سراسری (Global) شناخته می‌شود و به توابع geom انتقال داده می‌شود.

حال اگر در خود geom ها نیز از نگاشت استفاده کنیم ، به عنوان نگاشت محلیِ مخصوص آن لایه به حساب خواهد آمد و نگاشت سراسری را برای آن لایه گسترش (extend) می‌دهد و یا آن را دوباره‌نویسی (Overwrite) می‌کند.
(از همین ایده برای مشخص کردن داده متفاوت برای هر لایه نیز استفاده می‌شود.)

همان مثال بالا را دوباره به شیوه بهتر می‌نویسیم.
In [9]:
ggplot(data = mpg,mapping = aes(x = displ, y = hwy , color = drv)) + 
  geom_point() +
  geom_smooth(mapping = aes(linetype = drv))
`geom_smooth()` using method = 'loess' and formula 'y ~ x'



Statistical Transformations


(برای این بخش از مجموعه‌داده diamonds استفاده می‌کنیم.)
بعضی از نمودار ها همانند نمودار پراکنش به تغییری نیاز ندارند (هر نقطه بر اساس مختصات x و y آن رسم می‌شود) ، اما بعضی دیگر از نمودار‌ها نیاز به تغییرات آماری دارند.
به عنوان مثال نمودار میله‌ای زیر را در نظر بگیرید.
In [10]:
ggplot(data = diamonds) + 
  geom_bar(mapping = aes(x = cut))
در محور x ها ، متغیر برش (cut) را داریم و در محور y ها تعداد (count) را داریم اما count یکی از متغیر های مجموعه‌داده ما نمی‌باشد. این متغیر count ، از کجا می‌آید ؟
همانطور که گفته شد بعضی از نمودار‌ها همانند نمودار میله‌ای مقادیر جدیدی برای نمودار محاسبه می‌کنند . به الگوریتمی که این مقادیر جدید را محاسبه می‌کند stat (مخفف Statistical Transformation) می‌گویند.
یک stat یک مجموعه‌داده را به عنوان ورودی می‌گیرد و یک مجموعه‌داده با مقادیر جدید را برمی‌گرداند.
()geom_bar از ()stat_count استفاده می‌کند.
ما می‌توانیم از geom ها و stat ها به جای یکدیگر استفاده کنیم ، زیرا هر geom یک stat به‌طور پیش فرض دارد و همینطور هر stat یک geom.
In [11]:
ggplot(data = diamonds) + 
  stat_count(mapping = aes(x = cut))
با وجود این نکته می‌توانیم از geom ها بدون نگرانی از تغییرات آماری که در لایه های زیرین رخ می‌دهد ، استفاده کنیم.
اما حالاتی همانند حالت زیر از مواردی می‌باشد که باید stat به طور کامل مشخص شود :
می‌خواهیم stat پیش‌فرض را تغییر دهیم مثلا ، فرض کنید که ما count را از قبل در مجموعه‌داده خود داریم.
In [12]:
df <- data.frame(cut = c("Fair","Good","Very Good","Premium","Ideal"), count = c(1610,4906,12082,13791,21551))

ggplot(data = df) +
  geom_bar(mapping = aes(x = cut, y = count), stat = "identity")



ظاهر نمودارها


مهم‌ترین نکته در رسم نمودار توجه به این موضوع می‌باشد که نمودار‌ها باید به صورتی باشند که حتی کسی که کمترین اطلاعات را درباره موضوع دارد با نگاه به آن ها تمام اطلاعات را بفهمد.
نموداری خوب است که نیاز به کمترین توضیح ، برای انتقال اطلاعات داشته باشد.
از ویژگی های ظاهری مهم ، به داشتن عنوان و مشخص بودن اسم محور‌ها می‌توان اشاره کرد.

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

مثال :
In [13]:
ggplot(diamonds, aes(price, fill = cut)) +
  geom_histogram(binwidth = 500) +
  labs(title = "Histogram of Diamond Price",subtitle = "Colored by Diamond Cut",x = "Diamond Price ($)",y = "Frequency")
در گام‌های بعدی می‌توان به زیبایی بیشتر نمودار با افزودن تم‌ها ، تعیین مقیاس محورها و ... پرداخت.


نکات تکمیلی
برای مطالعه‌ی بیشتر می‌توانید به لینک مقابل مراجعه کنید: R Graphics
cheat sheet این مبحث نیز در کنار نوت‌بوک قرار داده شده که می‌توانید به آن مراجعه کنید.