Projekt 3

Opis projektu

Zadanie

W języku R jest wiele możliwości manipulacji ramkami danych. Jednym z takich pakietów jest dplyr jednak jego składania jest zdecydowanie różna od podobnych rozwiązań w innych językach. Ten projekt dotyczy zaproponowania rozwiązania, które pozwoli wykorzystywać pakiet dplyr ale w składni znacznie bardziej zbliżonej do modułu pandas z języka Python. Oczywiście znajmość języka Python nie jest wymagana do zrobienia tego projektu.

Ściśle zadanie polega na zaproponowaniu implementacji klasy pd, która pozwala na wykorzystanie wszystkich konstrukcji pakietu dplyr ale w składni zbliżonej do modułu pandas. Klasa pd musi pozwalać na definiowanie zbiorów danych. Poniżej jest przykład tworzenia instancji klasy pd.

### Tworzenie obiektu klasy pd
fileURL <- "http://michal.ramsza.org/lectures/2_r_programming/data/data_2.csv"
a <- pd$new(data = read.csv(file = fileURL)) 

W obiekcie a znajduje się wczytana ramka danych. Ramka ta jest obiektem klasy data.frame. Klasa pd dostarcza metodę convert(), która zmienia klasę zawartych danych z data.frame na df+tbl, tj. na tibble, oraz odwrtnie. Klasa pd zapewnia również metodę value(), która zwraca zapisaną ramkę danych. Możemy zobaczyć to w poniższym przykładzie.

### Zmiana klasy zapisanej ramki danych
class(a$value())
a$convert()
class(a$value())
a$convert()
head(a$value())

[1] "data.frame"
[1] "tbl_df"     "tbl"        "data.frame"
  Year_prod    Gas_type Engine_capacity Mileage  Price      Brand
1      2005      Diesel            2500  280000  20990       Audi
2      2009      Diesel            2200  170000  38000      Honda
3      2011      Diesel            1600   96000  22600 Volkswagen
4      2004 Benzyna+LPG            2494  198230  15000        BMW
5      2006      Diesel            2000  256000  16900 Volkswagen
6      2012     Benzyna            4000   67000 140000     Toyota
            Model  Voivodeship             City Negotiation
1           A4 B7 Dolnośląskie        Wałbrzych           0
2     Accord VIII  Mazowieckie            Płock           1
3          Polo V      Śląskie             Żory           0
4     Seria 3 E46  Mazowieckie         Warszawa           1
5       Passat B6      Śląskie            Bytom           1
6 Land Cruiser VI     Lubuskie Kostrzynnad Odrą           1

W powyższym przykładzie najpierw zmieniliśmy klasę ramki danych data.frame na tbl_df, sprawdziliśmy klasę a następnie ponownie na data.frame.

Następnie chcemy wykorzystać możliwości pakietu dplyr ale w innej składni. Klasa pd oferuje metodę op, która pozwala wykorzystać wszystkie możliwości pakietu dplyr. W poniższym przykładzie wykonujemy prostą analizę władowanej ramki danych a następnie tworzymy dwa proste histogramy.

### Operacje na danych
a$op(select(Mileage, Price, Brand))
a$op(filter(Mileage < 50000))
a$op(filter(Brand %in% c("Honda", "Fiat")))

### Tworzenie prostego 
ggplot(data = (a$value()), mapping = aes(x = Price)) +
    geom_histogram(bins = 100, aes(fill = Brand, color = Brand, y = ..density..)) +
    geom_density(fill = "blue", alpha = 0.2) + 
    facet_wrap(~ Brand, nrow = 2)

### Zapisywaie do pliku / w rozwiązaniu zdecydowanie można pominąć
dev.copy(device = png, "./fig1.png")
dev.off()

W powyższym przykładzie wykonaliśmy trzy proste działania. Pierwszy blok działań to kolejne operacje na danych, gdzie jako argument operatora op() podawane są dowolne komendy z pakietu dplyr. Drugi blok to przykładowe wykorzystanie pakietu ggplot2 do stworzenie wykresu, które jest zapisany do pliku w bloku ostatnim.

fig1.png

Figure 1: Przykładowe histogram stworzone w powyższy przykładzie

Oczywiście klasa pd zapewnia również łączenie operacji w ciąg oraz resetowanie wykonanych operacji. W poniższym przykładzie resetujemy wykonane operacje a następnie wykonujemy bardzo podobne operacje jak powyżej ale łącząc jest w ciąg.

### Resetowanie operacji
a$reset()

### Wykonywanie operacji w ciągu
a$op(select(Mileage, Price, Brand))$op(filter(Mileage < 50000))$op(filter(Brand %in% c("Toyota", "Fiat")))

### Tworzenie przykładowego wykresu
ggplot(data = (a$value()), mapping = aes(x = Price)) +
    geom_histogram(bins = 100, aes(fill = Brand, color = Brand, y = ..density..)) +
    geom_density(fill = "blue", alpha = 0.2) + 
    facet_wrap(~ Brand, nrow = 2)

### Zapisywaie do pliku / w rozwiązaniu zdecydowanie można pominąć
dev.copy(device = png, "./fig2.png")
dev.off()

Powyższy przykład tworzy następujący wykres (dla innych marek).

fig2.png

Figure 2: Przykładoww histogramy stworzone z wykorzystanie wiązania operacji

Moja przykładowa implementacja wykorzystuje model obiektowy R6 ale dla wygody zaproponowałem również metodę print() w modelu S3, któej wykorzystanie jest pokazane poniżej.

### Resetowanie wykonanych obliczeń
a$reset()

### Obliczenia
a$op(select(Brand, Mileage, Price))$op(filter(Price <= 500))
a$op(arrange(Brand, desc(Price)))

### Wyświetlenie wyników
a
   Brand Mileage Price
1 Daewoo  309376   500
2   Fiat  145500   400
3   Opel  296000   500
4 Toyota  260000   500
5 Toyota  312415   450

Jak widać, moja przykładowa implementacja wykorzystuje model obiektowy R6 ale w rozwiązaniu można wykorzytać dowolnym model obiektowy.

Techniczne warunki zaliczenie

Zadanie powinno być rozwiązane w pojedynczym skrypcie w pliku R. Rozwiązanie powinno zawierać definicje metod oraz przykładowe wykorzystanie (podobne do tych pokazanych) zdefiniowanych metod. Rozwiązania bez przykładów nie będą zaliczane. W rozwiązaniu nie wolno wykorzystywać dodatkowych pakietów, za wyjątkiem pakietu dplyr i ggplot2 w celu wykonania identycznych wykresów jak powyżej ale to nie jest konieczne, oraz pakietu R6 jeżeli implementacja będzie wykorzytywała model obiektowy R6. Proszę nie używać polskich znaków.

Data: 2021-05-04 Tue 00:00

Autor: Michał Ramsza

Created: 2021-05-04 Tue 19:49

Validate