Rysowanie

{ggplot2}


Wstęp


Na poprzednich zajęciach rysowaliśmy wykresy wbudowanym w R pakietem {graphics}. Na tych przyjrzymy się podstawom innego pakietu:

# biblioteka
# install.packages("ggplot2")
library(ggplot2)


Podstawowe elementy składni funkcji z pakietu {ggplot2}

“DataCamp.com”
“DataCamp.com”


“DataCamp.com”
“DataCamp.com”


“DataCamp.com”
“DataCamp.com”



Zbiór: Testy drogowe aut z 1974r.

str(mtcars) # ?mtcars
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...



Zbiór: Ceny i cechy jakościowe diamentów

dplyr::glimpse(diamonds) # ?diamonds
## Rows: 53,940
## Columns: 10
## $ carat   <dbl> 0.23, 0.21, 0.23, 0.29, 0.31, 0.24, 0.24, 0.26, 0.22, 0.23, 0.…
## $ cut     <ord> Ideal, Premium, Good, Premium, Good, Very Good, Very Good, Ver…
## $ color   <ord> E, E, E, I, J, J, I, H, E, H, J, J, F, J, E, E, I, J, J, J, I,…
## $ clarity <ord> SI2, SI1, VS1, VS2, SI2, VVS2, VVS1, SI1, VS2, VS1, SI1, VS1, …
## $ depth   <dbl> 61.5, 59.8, 56.9, 62.4, 63.3, 62.8, 62.3, 61.9, 65.1, 59.4, 64…
## $ table   <dbl> 55, 61, 65, 58, 58, 57, 57, 55, 61, 61, 55, 56, 61, 54, 62, 58…
## $ price   <int> 326, 326, 327, 334, 335, 336, 336, 337, 337, 338, 339, 340, 34…
## $ x       <dbl> 3.95, 3.89, 4.05, 4.20, 4.34, 3.94, 3.95, 4.07, 3.87, 4.00, 4.…
## $ y       <dbl> 3.98, 3.84, 4.07, 4.23, 4.35, 3.96, 3.98, 4.11, 3.78, 4.05, 4.…
## $ z       <dbl> 2.43, 2.31, 2.31, 2.63, 2.75, 2.48, 2.47, 2.53, 2.49, 2.39, 2.…



Zbiór: Irysy i ich cechy gatunkowe

str(iris) # ?iris
## 'data.frame':    150 obs. of  5 variables:
##  $ Sepal.Length: num  5.1 4.9 4.7 4.6 5 5.4 4.6 5 4.4 4.9 ...
##  $ Sepal.Width : num  3.5 3 3.2 3.1 3.6 3.9 3.4 3.4 2.9 3.1 ...
##  $ Petal.Length: num  1.4 1.4 1.3 1.5 1.4 1.7 1.4 1.5 1.4 1.5 ...
##  $ Petal.Width : num  0.2 0.2 0.2 0.2 0.2 0.4 0.3 0.2 0.2 0.1 ...
##  $ Species     : Factor w/ 3 levels "setosa","versicolor",..: 1 1 1 1 1 1 1 1 1 1 ...


Jak to wygląda w praktyce? Rozpatrzmy taki przykład jak używać pokazanych powyżej warstw (layers)/ elementów.

ggplot(data = mtcars, # Data The data-set being plotted.
       aes(x = cyl, y =mpg)) + # Aesthetics The scales onto which we map our data.
  geom_point() +# Geometries The visual elements used for our data.
  theme() # Themes All non-data ink.



Czasem potrzebujemy “poprawić” zmienną on the fly. Jest to możliwe w funkcjach rysujących {ggplot2} Poniżej zabieg, który zmieni nam wygląd osi. Cylindry do de facto zmienna kategorialna, otoczmy zatem funkcją factor() tę zmienną. Dzięki temu, pakiet nie będzie traktował informacji o cylindrach jak zmiennej ciągłej.

ggplot(mtcars,
       aes(factor(cyl), 
           mpg)) + 
  geom_point()


Dodajmy kolejny wymiar/ nową informację do naszego rysunku. Użyjmy pojemności silnika jako dodatkowej zmiennej wzbogacającej informacyjnie naszą wizualizację. Żeby się nie pogubić, przynajmniej na początku używajmy jawnie nazw argumentów funkcji.

ggplot(data = mtcars, 
       aes(x = wt, 
           y =  mpg, 
           color = disp)) +
  geom_point()


…albo podzielmy nasze rozrzucone punkty (auta) względem liczby cylindrów jakie posiadają

ggplot(mtcars, 
       aes(x = wt, 
           y =  mpg, 
           color = factor(cyl))) +
  geom_point()


Możemy dodawać różne “typy” wykresów na siebie, jak w przykładzie poniżej z użyciem data.frame diamonds

ggplot(diamonds, aes(x = carat,
                     y = price, 
                     color = clarity)) +
  geom_point() + # adds points (as in a scatter plot)
  geom_smooth( # adds a smooth trend curve.
    alpha=0.2 # to make the points 20% opaque
  ) 
## `geom_smooth()` using method = 'gam' and formula = 'y ~ s(x, bs = "cs")'

Aesthetics aes()


“DataCamp.com”
“DataCamp.com”


W nomenklaturze ggplot2 używa się pojęcia mapping do określenia “mapowania” zmiennych na osie.
Co do zasady, “wrzucamy” zmienne do pierwszego elementu budującego nasz kod.

ggplot(iris, aes(x = Sepal.Length, 
                 y = Sepal.Width, 
                 color = Species)) + 
  geom_point()


Zadziała jednak również takie rozwiązanie przedstawione poniżej. Przydatne w sytuacjach, gdy nie chcemy, żeby wszystkie zmienne “dziedziczyły” te same elementy estetyczne lub gdy zmienne, które rysujemy pochodzą z różnych zbiorów.

ggplot(iris) +
  geom_point(aes(x = Sepal.Length,
                 y = Sepal.Width,
                 col = Species))


Jeśli mamy do powtórzenia kilka wykresów opartych o te same dane i zmienne (np. aes(x = wt, y = mpg)), ale różniące się kwestiami estetycznymi, lub próbujemy je wzbogacić informacyjnie, ale nie wiemy jeszcze, który wykres trafi ostatecznie do naszego line manager’a, możemy część kodu przypisać do obiektu, a następnie wykorzystywać go.

(dane_wykres <- ggplot(mtcars,
                      aes(x = wt,
                          y = mpg)))

class(dane_wykres)
## [1] "ggplot2::ggplot" "ggplot"          "ggplot2::gg"     "S7_object"      
## [5] "gg"
str(dane_wykres)
## <ggplot2::ggplot>
##  @ data       :'data.frame': 32 obs. of  11 variables:
##  .. $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  .. $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  .. $ disp: num  160 160 108 258 360 ...
##  .. $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  .. $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  .. $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  .. $ qsec: num  16.5 17 18.6 19.4 17 ...
##  .. $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  .. $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  .. $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  .. $ carb: num  4 4 1 1 2 1 4 2 2 4 ...
##  @ layers     : list()
##  @ scales     :Classes 'ScalesList', 'ggproto', 'gg' <ggproto object: Class ScalesList, gg>
##     add: function
##     add_defaults: function
##     add_missing: function
##     backtransform_df: function
##     clone: function
##     find: function
##     get_scales: function
##     has_scale: function
##     input: function
##     map_df: function
##     n: function
##     non_position_scales: function
##     scales: NULL
##     set_palettes: function
##     train_df: function
##     transform_df: function
##     super:  <ggproto object: Class ScalesList, gg> 
##  @ guides     :Classes 'Guides', 'ggproto', 'gg' <ggproto object: Class Guides, gg>
##     add: function
##     assemble: function
##     build: function
##     draw: function
##     get_custom: function
##     get_guide: function
##     get_params: function
##     get_position: function
##     guides: NULL
##     merge: function
##     missing: <ggproto object: Class GuideNone, Guide, gg>
##         add_title: function
##         arrange_layout: function
##         assemble_drawing: function
##         available_aes: any
##         build_decor: function
##         build_labels: function
##         build_ticks: function
##         build_title: function
##         draw: function
##         draw_early_exit: function
##         elements: list
##         extract_decor: function
##         extract_key: function
##         extract_params: function
##         get_layer_key: function
##         hashables: list
##         measure_grobs: function
##         merge: function
##         override_elements: function
##         params: list
##         process_layers: function
##         setup_elements: function
##         setup_params: function
##         train: function
##         transform: function
##         super:  <ggproto object: Class GuideNone, Guide, gg>
##     package_box: function
##     print: function
##     process_layers: function
##     setup: function
##     subset_guides: function
##     train: function
##     update_params: function
##     super:  <ggproto object: Class Guides, gg> 
##  @ mapping    : <ggplot2::mapping> List of 2
##  .. $ x: language ~wt
##  ..  ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##  .. $ y: language ~mpg
##  ..  ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##  @ theme      : <theme>  Named list()
##  .. @ complete: logi FALSE
##  .. @ validate: logi TRUE
##  @ coordinates:Classes 'CoordCartesian', 'Coord', 'ggproto', 'gg' <ggproto object: Class CoordCartesian, Coord, gg>
##     aspect: function
##     backtransform_range: function
##     clip: on
##     default: TRUE
##     distance: function
##     draw_panel: function
##     expand: TRUE
##     is_free: function
##     is_linear: function
##     labels: function
##     limits: list
##     modify_scales: function
##     range: function
##     ratio: NULL
##     render_axis_h: function
##     render_axis_v: function
##     render_bg: function
##     render_fg: function
##     reverse: none
##     setup_data: function
##     setup_layout: function
##     setup_panel_guides: function
##     setup_panel_params: function
##     setup_params: function
##     train_panel_guides: function
##     transform: function
##     super:  <ggproto object: Class CoordCartesian, Coord, gg> 
##  @ facet      :Classes 'FacetNull', 'Facet', 'ggproto', 'gg' <ggproto object: Class FacetNull, Facet, gg>
##     attach_axes: function
##     attach_strips: function
##     compute_layout: function
##     draw_back: function
##     draw_front: function
##     draw_labels: function
##     draw_panel_content: function
##     draw_panels: function
##     finish_data: function
##     format_strip_labels: function
##     init_gtable: function
##     init_scales: function
##     map_data: function
##     params: list
##     set_panel_size: function
##     setup_data: function
##     setup_panel_params: function
##     setup_params: function
##     shrink: TRUE
##     train_scales: function
##     vars: function
##     super:  <ggproto object: Class FacetNull, Facet, gg> 
##  @ layout     :Classes 'Layout', 'ggproto', 'gg' <ggproto object: Class Layout, gg>
##     coord: NULL
##     coord_params: list
##     facet: NULL
##     facet_params: list
##     finish_data: function
##     get_scales: function
##     layout: NULL
##     map_position: function
##     panel_params: NULL
##     panel_scales_x: NULL
##     panel_scales_y: NULL
##     render: function
##     render_labels: function
##     reset_scales: function
##     resolve_label: function
##     setup: function
##     setup_panel_guides: function
##     setup_panel_params: function
##     train_position: function
##     super:  <ggproto object: Class Layout, gg> 
##  @ labels     : <ggplot2::labels>  Named list()
##  @ meta       : list()
##  @ plot_env   :<environment: R_GlobalEnv>
str(dane_wykres@data)
## 'data.frame':    32 obs. of  11 variables:
##  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
##  $ disp: num  160 160 108 258 360 ...
##  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
##  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
##  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
##  $ qsec: num  16.5 17 18.6 19.4 17 ...
##  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
##  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
##  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
##  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...


Przykład wykorzystania 3 zmiennych (i ich “mapowania”) oraz atrybutów wykresu.

dane_wykres +
  geom_point(aes(color = factor(cyl)),
             shape = 1, # ?points()
             size = 4)


Przykład wykorzystania 4 zmiennych (i ich “mapowania”) oraz atrybutów wykresu.

dane_wykres +
  geom_point(aes(color = factor(am), # Typically, the color aesthetic changes the outline of a geom 
                   fill = factor(cyl)), # and the fill aesthetic changes the inside
            shape = 21,  # ?points()
             size = 4, 
             alpha = 0.6)


Przykład wykorzystania wielu atrybutów wykresu.

ggplot(iris, aes(x = Sepal.Length, 
                 y = Sepal.Width)) + 
  geom_point(color ="blue",
             size = 8,
             shape = 4)


“DataCamp.com”
“DataCamp.com”



Uwaga o kolorach:

  • możemy używać niektórych angielskich nazw, np. “blue”, “darkblue”, “yellow”, etc.

  • możemy używać kodów kolorów RGB np.rgb(0, 1, 0), rgb((0:15)/15, green = 0, blue = 0, names = paste("red", 0:15, sep = ".")) -> ?rgb()

  • możemy używać kodów kolorów HEX “Hexadecimal is base-16 counting. You have 0 to 9, and A representing 10 up to F representing 15. Pairs of hexadecimal numbers give you a range from 0 to 255.”#000000” is “black” (no color), “#FFFFFF”

  • mamy też możliwość odwoływania się do licznych palet kolorów wbudowanych w R, np. {viridis}, {RColorBrewer}, {wesanderson} {ggsci}



Geometries


Pamiętamy jeszcze funkcję rownames(). Możemy z powodzeniem używać ich w ggplot2(). Przykład:

ggplot(mtcars, 
       aes(wt, mpg, color = factor(cyl))) +
  geom_text(label = rownames(mtcars), #
            color = "darkred")


Albo używać prostych obliczeń on the fly co, jeśli nie było do tej pory powiedziane, to niech wybrzmi teraz:

ggplot(mtcars, 
       aes(mpg, qsec, 
           color = factor(cyl), 
           shape = factor(am), 
           size = hp/wt)) +
  geom_point()


Poprawianie estetyczne wykresów Modifying aesthetics


Nazwy osi

# lab() -> to set the x- and y-axis labels. It takes strings for each argument
ggplot(mtcars, 
       aes(factor(cyl), 
           fill = factor(am))) +
  geom_bar() + # bar plot
  labs(x = "Number of Cylinders", 
       y = "Count") # Nazwy osi


Legenda

# scale_color_manual() defines properties of the color scale (i.e. axis). 
# The first argument sets the legend title. values is a named vector of colors to use

ggplot(mtcars, 
       aes(factor(cyl), 
           fill = factor(am))) +
  geom_bar() + # bar plot
  labs(x = "Number of Cylinders", 
       y = "Count") + # Nazwy osi
  scale_fill_manual("Transmission", # legend title
                    values = c("white", "#E41A1C")) # vector of colors, zwrócmy uwagę na "miks nazewniczy"


argument position w sekcji geom_*()

ggplot(mtcars, 
       aes(factor(cyl), 
           fill = factor(am))) +
  geom_bar(position = "stack") + # <- na sobie
  labs(x = "Number of Cylinders",
       y = "Count") +
  scale_fill_manual("Transmission", # legend title
                    values = c("#377EB8", "#E41A1C")) # vector of colors

# versus
ggplot(mtcars,
       aes(factor(cyl), 
           fill = factor(am))) +
  geom_bar(position = "dodge") + # <- obok siebie
  labs(x = "Number of Cylinders", 
       y = "Count")+
  scale_fill_manual("Transmission", 
                    values = c("#377EB8", "#E41A1C"))

# versus
ggplot(mtcars,
       aes(factor(cyl), 
           fill = factor(am))) +
  geom_bar(position = "fill") + # <- "do stu procent"
  labs(x = "Number of Cylinders", 
       y = "Count")+
  scale_fill_manual("Transmission", 
                    values = c("#377EB8", "#E41A1C"))


argument position - pozycja punktów

ggplot(iris, aes(x = Sepal.Length,
                 y = Sepal.Width,
                 color = Species)) +
  geom_point(position = "identity") # gdzie punkty o tych samych bądź zbliżonych wartościach nachodzą na siebie

# versus

ggplot(iris, aes(x = Sepal.Length,
                 y = Sepal.Width,
                 color = Species)) +
  geom_point(position = "jitter") # gdzie punkty nieco separujemy od siebie

# Inne pozycje (Adjustment for overlapping):
# - dodge
# - stack
# - fill
# - nudge
# - jitterdodge


Skalowanie osi

# ylim(lo, hi) lub ylim(c(lo, hi))

ggplot(mtcars, aes(mpg, 0)) +
  geom_jitter()

# versus
ggplot(mtcars, aes(mpg, 0)) +
  geom_jitter() +
  ylim(-2,2)



Geometries


“DataCamp.com”
“DataCamp.com”



geom_point()

Wizualizacja podsumowująca dwa zbiory.

library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
(iris %>%
    group_by(Species) %>%
    summarise_all(mean) -> iris.summary)
## # A tibble: 3 × 5
##   Species    Sepal.Length Sepal.Width Petal.Length Petal.Width
##   <fct>             <dbl>       <dbl>        <dbl>       <dbl>
## 1 setosa             5.01        3.43         1.46       0.246
## 2 versicolor         5.94        2.77         4.26       1.33 
## 3 virginica          6.59        2.97         5.55       2.03
ggplot(iris, 
       aes(x = Sepal.Length,
           y = Sepal.Width, 
           col = Species)) +
  geom_point(position = "jitter", 
             alpha = 0.6) + 
  geom_point(data = iris.summary, 
             shape = 21,
             size = 5,
             fill = "black",
             stroke = 2)

detach("package:dplyr", unload = TRUE)



geom_histogram()

ggplot(iris, 
       aes(x = Sepal.Width)) +
  geom_histogram(binwidth = 0.1)


ggplot(iris,
       aes(x = Sepal.Width,
           fill = Species)) +
  geom_histogram(binwidth = .1,
                 position = "stack")


ggplot(iris, 
       aes(x = Sepal.Width,
           fill = Species)) +
  geom_histogram(binwidth = .1,
                 position = "dodge")


ggplot(iris, 
       aes(x = Sepal.Width,
           fill = Species)) +
  geom_histogram(binwidth = .1,
                 position = "fill")



geom_bar() i geom_col()


Pierwsza funkcja zlicza wystąpienia, druga rysuje przygotowane wcześniej wartości. Zobaczmy na przykładzie:

ggplot(mtcars, 
       aes(factor(cyl))) +
  geom_bar() 

# versus
library(data.table) 

mtcars$auto <- rownames(mtcars)

mtcars2 <- data.table(mtcars)[, 
                              .(Count = uniqueN(auto)),
                              by = cyl] 

ggplot(mtcars2, 
       aes(x = factor(cyl),
           y = Count)) +
  geom_col() 



geom_line()


dplyr::glimpse(economics)
## Rows: 574
## Columns: 6
## $ date     <date> 1967-07-01, 1967-08-01, 1967-09-01, 1967-10-01, 1967-11-01, …
## $ pce      <dbl> 506.7, 509.8, 515.6, 512.2, 517.4, 525.1, 530.9, 533.6, 544.3…
## $ pop      <dbl> 198712, 198911, 199113, 199311, 199498, 199657, 199808, 19992…
## $ psavert  <dbl> 12.6, 12.6, 11.9, 12.9, 12.8, 11.8, 11.7, 12.3, 11.7, 12.3, 1…
## $ uempmed  <dbl> 4.5, 4.7, 4.6, 4.9, 4.7, 4.8, 5.1, 4.5, 4.1, 4.6, 4.4, 4.4, 4…
## $ unemploy <dbl> 2944, 2945, 2958, 3143, 3066, 3018, 2878, 3001, 2877, 2709, 2…


Bardzo dobry wybór do prezentowania czasu…

ggplot(economics,
       aes(x = date, 
           y = unemploy)) +
  geom_line()


library(ggplot2)

# Przykładowe dane
set.seed(42) # Ustawienie ziarna dla powtarzalności losowości
n <- 100 # Liczba obserwacji
dates <- seq(as.Date("2023-01-01"), 
             by = "days", 
             length.out = n)
y1 <- cumsum(rnorm(n))
y2 <- cumsum(rnorm(n))
y3 <- y1 + rnorm(n)

# Tworzenie ramki danych
data <- data.frame(dates = dates, 
                   y1 = y1, 
                   y2 = y2, 
                   y3 = y3)

# Tworzenie wykresu za pomocą ggplot2
ggplot(data, aes(x = dates)) +
  geom_line(aes(y = y1, 
                color = "Linia 1")) +
  geom_line(aes(y = y2, 
                color = "Linia 2")) +
  geom_area(aes(y = y3, 
                fill = "Obszar"),
            alpha = 0.5) +
  labs(x = "Czas", 
       y = "Wartość",
       title = "Zmyślny tytuł") +
  scale_color_manual(values = c("Linia 1" = "#CE50A7", 
                                "Linia 2" = "#380386")) +
  scale_fill_manual(values = "#B3EBDB") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, 
                                   hjust = 1)) # Obrót etykiet osi X


ggplot2() to nie tylko wykresy. To również np. mapy. Narysujmy województwa w Polsce.

# Instalacja
# install.packages(c("sf", "ggplot2", "dplyr", "rnaturalearth", "rnaturalearthdata"))

# ładowanie pakietów
library(sf)
library(ggplot2)
library(dplyr)
library(rnaturalearth)
library(rnaturalearthdata)

# Pobranie danych geograficznych Polski
poland <- rnaturalearth::ne_states(country = "Poland", 
                                   returnclass = "sf")

# Dodanie fikcyjnej zmiennej ciągłej
set.seed(123)  # Ustawienie ziarna dla powtarzalności wyników
poland$fictional_variable <- runif(nrow(poland), 
                                   min = 0, 
                                   max = 100)
# Definiowanie kolorów
custom_colors <- c("#CE50A7", "#F5DCED", "#EBB9DB", "#E195CA", "#A72E82", "#6F1F56")

# Rysowanie mapy
pol_map <- ggplot(data = poland) +
  geom_sf(aes(fill = fictional_variable)) +
  # scale_fill_viridis_c(option = "mako") +
  scale_fill_gradientn(colors = custom_colors) +
  theme_minimal() +
  labs(title = "Polska",
       subtitle = "Ważny wskaźnik",
       fill = "Fikcyjna wartość wskaźnika")

pol_map


Albo Francję z jej subregionami (departamentami).

# ładowanie pakietów

# library(ggplot2)
# library(dplyr)
# library(rnaturalearth)
# library(maps)
# library(rnaturalearthhires)

# Pobierz dane graniczne Francji z pakietu maps
france_map <- maps::map("france", 
                  plot = FALSE, 
                  fill = TRUE)
france_sf <- st_as_sf(france_map)

# Sprawdź strukturę danych
# print(france_sf)
# str(france_sf)

# Przygotuj fikcyjne dane dla każdej prowincji
set.seed(123) # Dla powtarzalności wyników

fake_data <- data.frame(
  ID = france_sf$ID,
  value = runif(n = nrow(france_sf),
                min = 0,
                max = 100)
  )

# Połącz fikcyjne dane z danymi przestrzennymi
france_sf <- france_sf %>%
  left_join(fake_data, by = "ID")

custom_colors <- c("#CDD9E0", "#A1B7C4", "#5B7E93", "#2E3F4A", "#1D1E27")

# Rysuj mapę przy użyciu ggplot2
(map_fr <- ggplot(data = france_sf) +
    geom_sf(aes(fill = value)) +
    scale_fill_gradientn(colors = custom_colors) +
    labs(title = "Francja", 
         fill = "Wartość wskaźnika",
         subtitle = "Departamenty",
         caption = "Uniwersytet Warszawski") +
    theme_minimal()
  )



Materiały z równoległych zajęć w postaci krótkich tutoriali na YT:



{plotly}


Materiały:


# install.packages("plotly")
library(plotly)
# install.packages("quantmod")
library(quantmod)


Kilka przykładów użycia zaczerpniętych z powyższej strony

Najpierw dane. Pamiętacie Państwo polecenie data() i dostępne “od ręki” zbiory? Skorzystajmy z USPersonalExpenditure z pakietu {datasets}. Wg dokumentacji: ‘This data set consists of United States personal expenditures (in billions of dollars) in the categories; food and tobacco, household operation, medical and health, personal care, and private education for the years 1940, 1945, 1950, 1955 and 1960.’

kableExtra::kbl(USPersonalExpenditure)
1940 1945 1950 1955 1960
Food and Tobacco 22.200 44.500 59.60 73.2 86.80
Household Operation 10.500 15.500 29.00 36.5 46.20
Medical and Health 3.530 5.760 9.71 14.0 21.10
Personal Care 1.040 1.980 2.45 3.4 5.40
Private Education 0.341 0.974 1.80 2.6 3.64


Pie Chart

# spolszczenie kategorii
rownames(USPersonalExpenditure) <- c("Żywność i tytoń", 
                                     "Prowadzenie gospodarstwa domowego",
                                     "Medycyna i zdrowie",
                                     "Opieka osobista", 
                                     "Edukacja prywatna")


# Tworzenie ramki danych z wydatkami osobistymi w USA (wcześniej była to macierz)
USPersonalExpenditure <- data.frame("Kategoria"=rownames(USPersonalExpenditure),
                                    USPersonalExpenditure)

# Wybór kolumny z kategoriami i wydatkami z 1960 roku
data <- USPersonalExpenditure[,c('Kategoria', 'X1960')]

# Tworzenie wykresu kołowego z użyciem plot_ly
fig <- plot_ly(data, labels = ~Kategoria,
               values = ~X1960, 
               type = 'pie')

# Ustawienia układu wykresu
fig <- fig %>% layout(title = 'Wydatki Stanów Zjednoczonych wg kategorii w 1960r.',
                      xaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE),
                      yaxis = list(showgrid = FALSE, zeroline = FALSE, showticklabels = FALSE))

# Wyświetlenie wykresu
fig


Bar Plot

# Tworzenie wektorów z nazwami zwierząt oraz liczbą zwierząt w zoo w Warszawie i Wrocławiu
zwierzeta <- c("żyrafy", "orangutany", "małpy")
WaW_Zoo <- c(15, 22, 32)
Wro_Zoo <- c(24, 14, 21)

# Tworzenie ramki danych z powyższymi wektorami
data <- data.frame(zwierzeta, 
                   WaW_Zoo, 
                   Wro_Zoo)

# Tworzenie wykresu słupkowego dla danych z zoo w Warszawie
fig <- plot_ly(data,
               x = ~zwierzeta,
               y = ~WaW_Zoo, 
               type = 'bar', 
               name = 'Warszawa Zoo')

# Dodanie danych z zoo we Wrocławiu do wykresu
fig <- fig %>% add_trace(y = ~Wro_Zoo, 
                         name = 'Wrocław Zoo')

# Ustawienia układu wykresu, w tym tytuł osi Y i tryb grupowania słupków
fig <- fig %>% layout(yaxis = list(title = 'Count'), 
                      barmode = 'group')

# Wyświetlenie wykresu
fig


CandleStick

# Pobieranie danych giełdowych dla akcji Apple (AAPL) z Yahoo Finance
library(quantmod)
getSymbols("AAPL", src='yahoo')
## [1] "AAPL"
# Tworzenie ramki danych z datami i wartościami akcji Apple
df <- data.frame(Date=index(AAPL),
                 coredata(AAPL))

# Wybór ostatnich 30 dni danych
df <- tail(df, 30)

# Tworzenie wykresu świecowego (candlestick) z użyciem plot_ly()
fig <- df %>% plot_ly(x = ~Date, type="candlestick",
                      open = ~AAPL.Open,
                      close = ~AAPL.Close,
                      high = ~AAPL.High, 
                      low = ~AAPL.Low)

# Ustawienia układu wykresu, w tym tytuł i ukrycie suwaka zakresu na osi X
fig <- fig %>% layout(title = "Podstawowy wykres świecowy",
                      xaxis = list(rangeslider = list(visible = F)),
                      yaxis = list(title = "Wartość"))

# Wyświetlenie wykresu
fig

BTW
Dane, które pobraliśmy za pomocą funkcji getSymbols("AAPL", src='yahoo'), pochodzą z Yahoo Finance. Funkcja getSymbols() z pakietu {quantmod} w R umożliwia pobieranie danych giełdowych z różnych źródeł, takich jak Yahoo Finance, FRED, OANDA i inne. Pobawcie się Państwo zresztą sami.

# FRED (Federal Reserve Economic Data)
getSymbols("GDP", src='FRED')
## [1] "GDP"
head(GDP, 5)
##                GDP
## 1947-01-01 243.164
## 1947-04-01 245.968
## 1947-07-01 249.585
## 1947-10-01 259.745
## 1948-01-01 265.742
tail(GDP, 5)
##                 GDP
## 2024-04-01 29147.04
## 2024-07-01 29511.66
## 2024-10-01 29825.18
## 2025-01-01 30042.11
## 2025-04-01 30485.73


# OANDA (dane walutowe)
getSymbols("EUR/USD", src='oanda')
## [1] "EUR/USD"
head(EURUSD, 5)
##            EUR.USD
## 2025-06-12 1.15594
## 2025-06-13 1.15386
## 2025-06-14 1.15510
## 2025-06-15 1.15491
## 2025-06-16 1.15658
tail(EURUSD, 5)
##            EUR.USD
## 2025-12-03 1.16552
## 2025-12-04 1.16605
## 2025-12-05 1.16492
## 2025-12-06 1.16440
## 2025-12-07 1.16438
class(EURUSD)
## [1] "xts" "zoo"
# Konwersja do ramki danych
df <- data.frame(Date=index(EURUSD), 
                 coredata(EURUSD))


Scatter with Line Mode

# Wczytywanie danych giełdowych dla akcji Apple, tym razem z pliku CSV zamieszczonego w sieci
stock <- read.csv(
  'https://raw.githubusercontent.com/plotly/datasets/master/finance-charts-apple.csv'
  )

# Tworzenie wykresu liniowego z użyciem plot_ly
fig <- plot_ly(stock, 
               type = 'scatter', 
               mode = 'lines') %>%
  add_trace(x = ~Date, 
            y = ~AAPL.High) %>%
  layout(showlegend = F)

# Ustawienia układu wykresu, w tym kolory linii zerowych i siatki oraz tło wykresu
fig <- fig %>%
  layout(xaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         yaxis = list(zerolinecolor = '#ffff',
                      zerolinewidth = 2,
                      gridcolor = 'ffff'),
         plot_bgcolor='#e5ecf6',
         width = 900)

# Wyświetlenie wykresu
fig



ggplotly()


Funkcja ggplotly() w R ma wiele zalet, które czynią ją niezwykle przydatną w tworzeniu interaktywnych wizualizacji danych. Te zalety to m.in.:

  • Interaktywność: ggplotly() przekształca statyczne wykresy ggplot2 w interaktywne grafiki, które umożliwiają użytkownikom zoom’owanie, przesuwanie oraz wyświetlanie dodatkowych informacji w dymkach narzędziowych.

  • Łatwość użycia: Jeśli już znasz ggplot2, dodanie interaktywności jest proste i wymaga tylko jednej dodatkowej linii kodu. Wystarczy użyć ggplotly() na obiekcie ggplot2.

  • Dynamiczne etykiety osi: Funkcja ta pozwala na dynamiczne generowanie etykiet osi, co jest szczególnie przydatne podczas interakcji takich jak zoom’owanie i przesuwanie.

# ?ggplotly()


Pamiętacie Państwo mapę Polski z województwami?

pol_map


Zastosujmy funkcję ggplotly() na tym obiekcie.

# library(plotly)
plotly::ggplotly(pol_map)


Albo uczyńmy nieco bardziej interaktywną mapę Francji. Nasz oryginalny obiekt:

map_fr

i po użyciu funkcji ggplotly()

plotly::ggplotly(map_fr)





{highcharter}


Mapy


Można stworzyć mapę świata i nałożyć na nią punkty, wartości, etc. Przykład poniżej

# Instalacja i załadowanie pakietów
# install.packages("highcharter")
# install.packages("dplyr")
# install.packages("sf")

library(highcharter)
library(dplyr)
library(sf)

# Przykładowe dane z miastami, typami i kolorami
cities <- data.frame(
  city = c("Warszawa", "Krakow", "Gdańsk", "Berlin", "Paryż", 
           "Londyn", "Nowy Jork", "Los Angeles", "Tokio", "Sydney"),
  lat = c(52.2297, 50.0647, 54.3520, 52.5200, 48.8566, 51.5074, 40.7128, 34.0522, 35.6895, -33.8688),
  lon = c(21.0122, 19.9450, 18.6466, 13.4050, 2.3522, -0.1278, -74.0060, -118.2437, 139.6917, 151.2093),
  type = c("Category 1", "Category 1", "Category 1", "Category 1", "Category 1", 
           "Category 1", "Category 2", "Category 2", "Category 2", "Category 2"),
  color = c("#CE50A7", "#CE50A7", "#CE50A7", "#CE50A7", "#CE50A7", 
            "#CE50A7", "#29A180", "#29A180", "#29A180", "#29A180")
)

# Konwersja danych do formatu sf
cities_sf <- st_as_sf(cities, coords = c("lon", "lat"), crs = 4326)

# Tworzenie mapy z czarnym tłem, szarymi kontynentami i funkcją zoomowania
hcmap("custom/world", showInLegend = FALSE) %>%
  hc_add_series(
    data = cities %>% filter(type == "Category 1"), 
    type = "mappoint", 
    hcaes(lat = lat, lon = lon, name = city),
    color = "#CE50A7",
    name = "Category 1",
    marker = list(symbol = "circle"),
    showInLegend = TRUE
  ) %>%
  hc_add_series(
    data = cities %>% filter(type == "Category 2"), 
    type = "mappoint", 
    hcaes(lat = lat, lon = lon, name = city),
    color = "#29A180",
    name = "Category 2",
    marker = list(symbol = "circle"),
    showInLegend = TRUE
  ) %>%
  hc_title(text = "Network", style = list(color = "#FFFFFF")) %>%
  hc_chart(backgroundColor = "#000000") %>%
  hc_plotOptions(
    map = list(
      nullColor = "#303030",
      borderColor = "#606060",
      borderWidth = 0.5
    )
  ) %>%
  hc_mapNavigation(enabled = TRUE) %>%
  hc_legend(
    enabled = TRUE,
    itemStyle = list(color = "#FFFFFF")
  )





{markdown}


“RStudio”
“RStudio”

Materiały:


R {Markdown} to pakiet dzięki któremu, otrzymujemy do dyspozycji narzędzie do prezentowania wyników naszych prac. Możemy tworzyć z jego pomocą zarówno płaskie dokumenty jak pdf’y czy pliki Word’a, jak również interaktywne dashboardy w formie stron html.

Rozpoczęcie pracy


W Rstudio wybieramy z menu File -> New File -> R Markdown. Lub klikając ikonkę New file wybieramy jak niżej:

“Screenshot from RStudio”
“Screenshot from RStudio”


Pojawi się menu, w którym możemy wpisać autora dokumentu, tytuł, datę (modyfikowalne na każdym etapie pracy) oraz wybrać jaki ma być docelowy format dokumentu.

“Screenshot from RStudio”
“Screenshot from RStudio”


Po kliknięciu OK uruchamia nam się template dokumentu, na którym możemy rozpocząć pracę.

“Screenshot from RStudio”
“Screenshot from RStudio”


W skrypcie można wyróżnić co najmniej 3 elementy:

  • YAML, czyli nagłówek dokumentu, ujęty między --- ---

  • chunk, powtarzającą się część dokumentu ujęta między ```r ```

  • przestrzeń między chunk’ami, służąca do uzupełnienia naszego dokumentu/ raportu tekstem

“DataCamp.com”
“DataCamp.com”


Żeby zobaczyć jak wygląda wynik naszej pracy (póki co bazując na zawartości treści suflowanych nam przez template), należy plik zapisać na dysku, po czym uruchomić ikonkę Knit. Można też skorzystać ze skrótu klawiszowego Ctrl+Shift+k (za pierwszym razem poprosi o nadanie nazwy plikowi .RMD, zapisanie go na dysku, w pozostałych sytuacjach będzie już tylko kompilował skrypt).


Formatowanie


Dodatkowymi materiałami szkoleniowymi, są udostępnione Państwu na google drive dwa dokumenty PDF pokazujące m.in. opcje formatowania. Prośba o uruchomienie ich w tle i próbę zastosowania we właśnie skompilowanym dokumencie.

Kilka przykładów poniżej:


nagłówki
używamy #, każde zwielokrotnienie hash’a daje kolejne sub nagłówki

“DataCamp.com”
“DataCamp.com”


tekst pogrubiony
tekst **pogrubiony**


tekst pochylony i pochylony
tekst *pochylony* i _pochylony_


tekst przekreślony
tekst ~~przekreślony~~

“DataCamp.com”
“DataCamp.com”


Tekst w stylistyce komend R możemy wyświetlać kończąc i zaczynając apostrofem: komenda R lub potrójnym apostrofem (też tzw. inline chunk).


indeks górny: y1 lub y1
y<sup>1</sup> lub y^1^


indeks dolny: y1 lub y1
y<sub>1</sub> lub y~1~


od nowej linijki: dwie spacje na końcu linijki lub html’owy <br>
nowy akapit: wolna linijka


lista 1 :

  • Punkt 1

  • Punkt 2

  • Punkt 3

Kod w R:

* Punkt 1 - Punkt 2 + Punkt 3


lista 2:

  1. Punkt
  • podpunkt 1.1
  • podpunkt 1.2
  1. Punkt
  2. Punkt
  3. Punkt

Kod w R: 1. Punkt + podpunkt 1.1 + podpunkt 1.2 2. Punkt 3. Punkt 4. Punkt


cycaty:

Tu następuje jakiś kopipejst z internetów z paulo coelho

> Tu następuje jakiś kopipejst z internetów z paulo coelho


wzory (https://en.wikipedia.org/wiki/MathJax)

\[\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}\]
$$\sum_{i=0}^n i^2 = \frac{(n^2+n)(2n+1)}{6}$$

\[\Biggl(\biggl(\Bigl(\bigl((x)\bigr)\Bigr)\biggr)\Biggr)\]
$$\Biggl(\biggl(\Bigl(\bigl((x)\bigr)\Bigr)\biggr)\Biggr)$$


linki: Uniwerek Warszawski
[Uniwerek Warszawski](http://www.uw.edu.pl)


Zadzialają wszelkie wstawki html’owe: Czerwony tekst
<font color="red">Czerwony tekst</font>


tabele: (bardziej fancy będziemy tworzyć odpowiednimi pakietami)

Kolumna1 Kolumna2 Kolumna3 Kolumna4
13 69 13 69
666 666 666 666
7 7 7 7


| Kolumna1 | Kolumna2 | Kolumna3 | Kolumna4 | |---------:|:---------|:--------:|----------| | 13 | 69 | 13 | 69 | | 666 | 666 | 666 | 666 | | 7 | 7 | 7 | 7 |


Przypis:


Coś pożyczone z sieci 1

Coś pożyczone z sieci [^1]

[^1]: A tu skąd rzecz została znaleziona

A to tylko drobny przykład arsenału opcji…



Chunk

To przestrzeń do wrzucania surowego kodu R’owego. Chunki mają bardzo dużo opcji dodatkowych - które mają nam pomóc konfigurować i kontrolować informacje, które będą pojawiały się na ekranie. Więcej w materiale dodatkowym na google drive w pliku pdf. Zobaczmy przykład:

“DataCamp.com”
“DataCamp.com”



Konfigurowanie chunk’a

Ten chunk się nawet nie pojawi {r eval=FALSE, include=FALSE}



Ten chunk wyrzuci dodatkowe informacje {r message=TRUE, warning=TRUE, paged.print=TRUE}

library(dplyr)



A ten się po prostu wykona {r message=FALSE, warning=FALSE, paged.print=FALSE}

library(dplyr)



“DataCamp.com”
“DataCamp.com”



Inline chunk `r `

W zbiorze danych znajduje się 32 samochodów, a ich średnia spalania wynosi 20.09 miles per gallon

"W zbiorze danych znajduje się `r nrow(mtcars)` samochodów, a ich średnia spalania wynosi `r round(mean(mtcars$mpg), 2)` miles per gallon"
## [1] "W zbiorze danych znajduje się `r nrow(mtcars)` samochodów, a ich średnia spalania wynosi `r round(mean(mtcars$mpg), 2)` miles per gallon"



w R Markdown sesja R, w której pracujemy jest odrębna od sesji przy kompilowaniu dokumentów. Zatem wszystkie biblioteki i dokumenty muszą być wczytane do pamięci w ramach kompilowanego dokumentu. Polecenia typu library() muszą być użyte w dokumencie chociaż raz, najlepiej w pierwszym chunk’u (tzw. setup chunk), skąd inne ustawienia będą “dziedziczone”. Poszczególne chunk’i widzą i przekazują swoje wyniki.

YAML

Sekcja na górze dokumentu. Nazwa jest akronimem rekurencyjnym, czyli odnoszącym się do samego siebie (rozwinięcie to YAML Ain’t Markup Language).


Dokument, który aktualnie mają Państwo przed oczami ma takiego YAML’a

'---
title: "Zajęcia 9"
author: "Michał Maluchnik"
date: "`r Sys.Date()`"
output: 
  html_document:
    toc: true
    toc_float: true
    toc_collapsed: true
    toc_depth: 4
    number_sections: false
    theme: lumen
    css: styles.css
---'
## [1] "---\ntitle: \"Zajęcia 9\"\nauthor: \"Michał Maluchnik\"\ndate: \"`r Sys.Date()`\"\noutput: \n  html_document:\n    toc: true\n    toc_float: true\n    toc_collapsed: true\n    toc_depth: 4\n    number_sections: false\n    theme: lumen\n    css: styles.css\n---"


Kilka opcji formatowania spisu treści:

  • toc - czy ma być widoczny spis treści? (true/false)
  • toc_depth - do jakiej głębokości nagłówków spis treści ma być formatowany?
  • number_sections - czy sekcje mają być numerowane automatycznie?
  • toc_float - czy spis treści ma być ruchomy?
  • collapsed - czy spis treści ma się responsywnie zwijać i rozwijać, w zależności od tego, na jakiej głębokości się znajdujemy?
  • smooth_scroll - czy przy kliknięciu nagłówka w spisie treści ma być animacja scroll’owania?


Styl

W Markdown można skorzystać z predifiniowanych styli (themes) i formatowania składni. Style są zaczerpnięte z biblioteki Bootstrap (HTML-owej), więcej na: https://bootswatch.com/
Dostępne style: default, cerulean, journal, flatly, readable, spacelab, united, cosmo, lumen, paper, sandstone, simplex, oraz yeti.





Tabele

{DT}


Główną funkcją pakietu {DT} jest datatable().

# install.packages("DT")
library(DT)
datatable(mtcars) # <- po prostu, a już zobaczmy jaki bajer


Pod adresem: https://rstudio.github.io/DT/ znajduje się obszerny opis jak używać poszczególnych parametrów funkcji datatable(). Warto przejrzeć pokazane tam przykłady i wykorzystać użyty kod do swoich potrzeb.

# library(DT)
iris2 <- iris
names(iris2) <- c("Długość działek kielicha",
                 "Szerokość działek kielicha",
                 "Długość płatków",
                 "Szerokość płatków",
                 "Gatunek")

datatable(iris2
          , rownames = FALSE
          , options = list(
            autoWidth = TRUE, # żeby sterować szerokością kolumn
            columnDefs = list(list(width = '10px', targets = c(0,2)), # ręczne ustawianie szerokości kolumn 1 i 3 (gdy rownames = TRUE, wówczas c(1,3)), bo 'The JavaScript index of the 6th column is 5'
                              list(className = 'dt-center', targets = 4)) # centrowanie piątej kolumny
            , pageLength = 10 # liczba pokazywanych wierszy
            , lengthMenu = c(1, 10, 15, 20) # kastomizacja search box'a
            , order = list(list(0, 'asc'), list(1, 'desc'))# pierwsza kolumna posortowana rosnąco, druga malejąco
            , initComplete = JS(
              "function(settings, json) {",
              "$(this.api().table().header()).css({'background-color': '#000', 'color': '#fff'});", # zmiana kolorów nazw kolumn
              "}")
            , searchHighlight = TRUE # koloruje wyszukiwane frazy w Search Box
            ) 
          )


datatable(iris) %>% 

  # Formatowanie kolumny 'Sepal.Length' - pogrubienie tekstu dla wartości powyżej 5
  formatStyle('Sepal.Length', 
              fontWeight = styleInterval(5, c('normal', 'bold'))) %>%

  # Formatowanie kolumny 'Sepal.Width' - zmiana koloru tekstu i tła w zależności od wartości
  formatStyle('Sepal.Width',
              color = styleInterval(c(3.4, 3.8), c('white', 'blue', 'red')),
              backgroundColor = styleInterval(3.4, c('gray', 'yellow'))) %>%

  # Formatowanie kolumny 'Petal.Length' - dodanie paska koloru w tle
  formatStyle('Petal.Length', background = styleColorBar(iris$Petal.Length, 'steelblue'),
              backgroundSize = '100% 90%',
              backgroundRepeat = 'no-repeat',
              backgroundPosition = 'center') %>%

  # Formatowanie kolumny 'Species' - obrót tekstu i zmiana koloru tła w zależności od gatunku
  formatStyle('Species',
              transform = 'rotateX(45deg) rotateY(20deg) rotateZ(30deg)',
              backgroundColor = styleEqual(
                unique(iris$Species), c('lightblue', 'lightgreen', 'lightpink')
                )
              )


{kableExtra}


# install.packages("kableExtra")
library(kableExtra)
kbl(mtcars) # <- po prostu, bez żadnych parametrów
mpg cyl disp hp drat wt qsec vs am gear carb auto
Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 Mazda RX4
Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 Mazda RX4 Wag
Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 Datsun 710
Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 Hornet 4 Drive
Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 Hornet Sportabout
Valiant 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 Valiant
Duster 360 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 Duster 360
Merc 240D 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 Merc 240D
Merc 230 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 Merc 230
Merc 280 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 Merc 280
Merc 280C 17.8 6 167.6 123 3.92 3.440 18.90 1 0 4 4 Merc 280C
Merc 450SE 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3 Merc 450SE
Merc 450SL 17.3 8 275.8 180 3.07 3.730 17.60 0 0 3 3 Merc 450SL
Merc 450SLC 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3 Merc 450SLC
Cadillac Fleetwood 10.4 8 472.0 205 2.93 5.250 17.98 0 0 3 4 Cadillac Fleetwood
Lincoln Continental 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4 Lincoln Continental
Chrysler Imperial 14.7 8 440.0 230 3.23 5.345 17.42 0 0 3 4 Chrysler Imperial
Fiat 128 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1 Fiat 128
Honda Civic 30.4 4 75.7 52 4.93 1.615 18.52 1 1 4 2 Honda Civic
Toyota Corolla 33.9 4 71.1 65 4.22 1.835 19.90 1 1 4 1 Toyota Corolla
Toyota Corona 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1 Toyota Corona
Dodge Challenger 15.5 8 318.0 150 2.76 3.520 16.87 0 0 3 2 Dodge Challenger
AMC Javelin 15.2 8 304.0 150 3.15 3.435 17.30 0 0 3 2 AMC Javelin
Camaro Z28 13.3 8 350.0 245 3.73 3.840 15.41 0 0 3 4 Camaro Z28
Pontiac Firebird 19.2 8 400.0 175 3.08 3.845 17.05 0 0 3 2 Pontiac Firebird
Fiat X1-9 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1 Fiat X1-9
Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2 Porsche 914-2
Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2 Lotus Europa
Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4 Ford Pantera L
Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6 Ferrari Dino
Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8 Maserati Bora
Volvo 142E 21.4 4 121.0 109 4.11 2.780 18.60 1 1 4 2 Volvo 142E


Pod adresem: https://cran.r-project.org/web/packages/kableExtra/vignettes/awesome_table_in_html.html znajdziemy przykłady wykorzystania pakietu {kableExtra}. Warto czytając tutorial’e tego typu, kopiować przedstawione tam fragmenty kodu, zobaczyć czy działają i modyfikować je pod własne potrzeby.

library(knitr)
library(kableExtra)
library(dplyr)

# Tworzenie tabeli
tabela <- data.frame(
  Kategoria = c("A", "B", "C", "D"), 
  Data = c(Sys.Date(), Sys.Date()+1, Sys.Date()+2, Sys.Date()+3)
)

# Definicja funkcji kolorującej komórki w zależności od wartości kategorii
kolorowanie_komorek <- function(kategoria) {
  case_when(
    kategoria == "A" ~ 'lightblue',
    kategoria == "B" ~ 'lightgreen',
    kategoria == "C" ~ 'lightyellow',
    TRUE ~ 'lightcoral'
  )
}

# Kolorowanie tła komórek w kolumnie "Data" na podstawie wartości w kolumnie "Kategoria"
tabela_format <- tabela %>%
  mutate(Data = cell_spec(Data, 
                          color = "white", 
                          background = kolorowanie_komorek(Kategoria))) %>%
  kable("html",
        escape = FALSE) %>%
  kable_styling()

# Wyświetlenie tabeli
tabela_format
Kategoria Data
A 2025-12-08
B 2025-12-09
C 2025-12-10
D 2025-12-11


# Podział kolumny 'mpg' z danych 'mtcars' na listy według liczby cylindrów
mpg_list <- split(mtcars$mpg, mtcars$cyl)

# Podział kolumny 'disp' z danych 'mtcars' na listy według liczby cylindrów
disp_list <- split(mtcars$disp, mtcars$cyl)

# Tworzenie ramki danych do przechowywania wykresów inline
inline_plot <- data.frame(cyl = c(4, 6, 8),
                          mpg_box = "",
                          mpg_hist = "",
                          mpg_line1 = "", 
                          mpg_line2 = "",
                          mpg_points1 = "",
                          mpg_points2 = "", 
                          mpg_poly = "")

# Formatowanie tabeli z wykresami inline
inline_plot %>%
  
  kbl(booktabs = TRUE) %>%  # Tworzenie tabeli z opcją 'booktabs'
  
  kable_paper(full_width = FALSE) %>%  # Formatowanie tabeli w stylu 'kable_paper'
  
  # Dodanie wykresu pudełkowego do kolumny 2
  column_spec(2, image = spec_boxplot(mpg_list)) %>%
  
  # Dodanie histogramu do kolumny 3
  column_spec(3, image = spec_hist(mpg_list)) %>%
  
  # Dodanie wykresu liniowego z tymi samymi ograniczeniami do kolumny 4
  column_spec(4, image = spec_plot(mpg_list, same_lim = TRUE)) %>%
  
  # Dodanie wykresu liniowego z różnymi ograniczeniami do kolumny 5
  column_spec(5, image = spec_plot(mpg_list, same_lim = FALSE)) %>%
  
  # Dodanie wykresu punktowego do kolumny 6
  column_spec(6, image = spec_plot(mpg_list, type = "p")) %>%
  
  # Dodanie wykresu punktowego z danymi 'disp' do kolumny 7
  column_spec(7, image = spec_plot(mpg_list, disp_list, type = "p")) %>%
  
  # Dodanie wykresu wielomianowego do kolumny 8
  column_spec(8, image = spec_plot(mpg_list, polymin = 5))
cyl mpg_box mpg_hist mpg_line1 mpg_line2 mpg_points1 mpg_points2 mpg_poly
4
6
8



Praca domowa

Proszę przeanalizować tutorial’e podlinkowane w tej prezentacji dotyczące pakietów {markdown}(narzędzie do postawienia raportu końcowego) , {DT} oraz {kableExtra} (żeby w raporcie wrzucić ładne tabele) i {ggplot2} (żeby zainspirować się/ pożyczyć kod do zrobienia ciekawych, informatywnych wizualizacji w raporcie).

Rozwiązanie

Sugeruję wykorzystać nadchodzący czas wolny do rozpoczęcia prac nad produktem zaliczającym warsztaty Proszę zgłaszać się każdorazowo po zajęciach, jeśli będą Państwo borykać się z jakimiś problemami technicznymi, mieli wątpliwości, pytania, etc.




Źródła i inspiracje pomocne w przygotowaniu niniejszej prezentacji:


  1. A tu skąd rzecz została znaleziona
    ↩︎