Statystyka i Analiza danych

Laboratorium 2 - Wprowadzenie do R

In [1]:
options(repr.plot.width = 10, repr.plot.height = 10)

Konsola języka R może służyć jako kalkulator. Wypróbuj podstawowe operacje arytmetyczne: dodawanie, odejmowanie, dzielenie, mnożenie, potęgowanie (^), operator modulo (%%). Aby wykonać kod z pola naciśnij Ctrl+Enter, aby skorzystać w autouzupełniania wciśnij Tab.

In [2]:
2^8
256
In [3]:
5/2
2.5

Szeregi rozdzielcze

Szeregi rozdzielcze można łatwo skonstruować w pakiecie R. W tym celu najpierw wprowadźmy do systemu nasze dane. Możemy to zrobić np. poprzez ręczne utworzenie wektora z danymi wydając polecenie:

In [4]:
dane <- c(1123, 198, 473, 784, 305, 423, 397, 298, 698, 237)

Operator <- oznacza przypisanie, a funkcja c() tworzy z podanych liczb wektor. Wektor w R nie koniecznie musi zawierać liczby -- może to być dowolny typ danych np. ciąg znaków, jednakże dane w całym wektorze zawsze muszą być jednakowego typu.

Aby utworzyć szereg rozdzielczy musimy podzielić nasze dane na przedziały. Możemy zrobić to za pomocą funkcji cut(dane, breaks=liczba_przedziałów) w której musimy ręcznie wyspecyfikować liczbę przedziałów poprzez podanie argumentu breaks=. Załóżmy, że dla naszego krótkiego wektora danych wystarczą 3 przedziały i wywołajmy polecenie:

In [5]:
dane_w_przedzialach <- cut(dane, breaks = 3)
print(dane_w_przedzialach)
 [1] (815,1.12e+03] (197,506]      (197,506]      (506,815]      (197,506]     
 [6] (197,506]      (197,506]      (197,506]      (506,815]      (197,506]     
Levels: (197,506] (506,815] (815,1.12e+03]

Utworzona właśnie zmienna dane_w_przedzialach nie jest już wektorem, ale zmienną typu factor.

In [6]:
is.vector(dane_w_przedzialach)
is.factor(dane_w_przedzialach)
FALSE
TRUE

Stało się tak dlatego, że funkcja cut() po określeniu zakresu przedziałów automatycznie przekonwertowała wszystkie wartości wektora dane na nazwy odpowiadających im przedziałów. Dane zmieniły więc swój typ i są teraz typu jakościowego. Zwróć uwagę, że po wypisaniu zawartości naszej zmiennej pojawiła się dodatkowa linijka Levels: ... która pokazuje kolejne możliwe wartości naszej zmiennej nominalnej.

Mając tak przygotowane dane, wystarczy zliczyć wartości poszczególnych przedziałów funkcją table().

In [7]:
table(dane_w_przedzialach)
dane_w_przedzialach
     (197,506]      (506,815] (815,1.12e+03] 
             7              2              1 

Ćwiczenia

Podczas wykonywania tutoriala poznałeś typ factor służący do przechowywania wartości nominalnych. Możesz przekonwertować wektor tekstów do wektora typu factor poprzez wywołanie factor(nazwa_wektora).

Stwórz wektor o wartościach ["Mężczyzna", "Kobieta", "Kobieta", "Mężczyzna", "Mężczyzna"] i przekonwertuj do typu factor.

Bez konwersji na factor:

In [8]:
gender_string<-c("Mężczyzna", "Kobieta", "Kobieta", "Mężczyzna", "Mężczyzna")

Spróbuj porównać (np. znakiem większości) pierwszy i drugi element nowo utworzonego wektora.

In [9]:
gender_string[1]>gender_string[2]
TRUE

^Nastąpiło porównanie leksykograficzne. Chcemy żeby wektor przechowywał wartości nominalne (a nie ciągi znaków), więc potrzebna jest konwersja na factor (i przypisanie wyniku konwersji do zmiennej):

In [10]:
gender_factor  <- factor(gender_string)
In [11]:
gender_factor[1]>gender_factor[2]
Warning message in Ops.factor(gender_factor[1], gender_factor[2]):
“‘>’ not meaningful for factors”
<NA>

Możliwe jest też utworzenie wektora wartości porządkowych:

In [12]:
gender_ordered  <- factor(gender_string, ordered = T)
In [13]:
gender_ordered[1]>gender_ordered[2]
TRUE

Zmiana porządku wartości wektora:

In [14]:
gender_ordered  <- factor(gender_string, ordered = T, levels = c("Mężczyzna", "Kobieta"))
In [15]:
gender_ordered[1]>gender_ordered[2]
FALSE

Typ wektorowy pozwala na przechowywanie danych tylko jednego typu. Co się stanie jeśli spróbujesz utworzyć wektor zawierający np. liczby i ciągi znaków?

In [16]:
c(1,"SD")
  1. '1'
  2. 'SD'

Poniższy wektor

In [17]:
ulubiony_przedmiot <- c("SiAD", "PP", "PO", "AiSD", "MD", "PO", "SiAD", "SiAD", "SiAD", "AiSD", "SiAD", "PO", "SiAD", "PP", "SiAD", "SiAD")

zawiera dane o ulubionych przedmiotach studentów. Stwórz tablekę pokazującą ilu studentów lubi dany przedmiot.

In [18]:
table(ulubiony_przedmiot)
ulubiony_przedmiot
AiSD   MD   PO   PP SiAD 
   2    1    3    2    8 

Operacje na wektorach

Język R, podobnie jak poznany na przedmiocie ,,Narzędzia informatyki'' MATLAB/Octave, operuje na wektorach i macierzach. Pracując w R możesz więc wykonywać operacje na całych wektorach (tak samo jak w MATLAB).

Dla szybkiego przypomnienia, przetestuj w R następujące komendy:

In [19]:
dane <- c(1123, 198, 473, 784, 305, 423, 397, 298, 698, 237)
dane*2
  1. 2246
  2. 396
  3. 946
  4. 1568
  5. 610
  6. 846
  7. 794
  8. 596
  9. 1396
  10. 474
In [20]:
dane[5]
305
In [21]:
dane[c(1,5)]
  1. 1123
  2. 305
In [22]:
dane > 500
  1. TRUE
  2. FALSE
  3. FALSE
  4. TRUE
  5. FALSE
  6. FALSE
  7. FALSE
  8. FALSE
  9. TRUE
  10. FALSE
In [23]:
dane[dane > 500]
  1. 1123
  2. 784
  3. 698

Ćwiczenia

Spróbuj wyciągnąć z wektora dane element o niecałkowitym indeksie np.~2.5. Co się stało?

In [24]:
dane[2.5]
198

Wypisz z wektora dane wszystkie liczby parzyste.

In [25]:
dane[dane%%2 == 0]
  1. 198
  2. 784
  3. 298
  4. 698

Oprócz funkcji c() możemy stworzyć wektor poprzez wywołanie funkcji seq(od, do, co_ile) np. seq(1,10,1) wypisze wszystkie liczby od 1 do 10. W przypadku generowania kolejnych cyfr można też posłużyć się konstrukcją od:do np. 1:10.

Wygeneruj wszystkie liczby od 1 do 20

In [26]:
1:20
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20

Wygeneruj wszystkie liczby parzyste mniejsze od 50

In [27]:
seq(2,49,2)
  1. 2
  2. 4
  3. 6
  4. 8
  5. 10
  6. 12
  7. 14
  8. 16
  9. 18
  10. 20
  11. 22
  12. 24
  13. 26
  14. 28
  15. 30
  16. 32
  17. 34
  18. 36
  19. 38
  20. 40
  21. 42
  22. 44
  23. 46
  24. 48

Wygeneruj wszystkie wielokrotności liczby 3 mniejsze od 100, a następnie zlicz ile z nich kończy się daną cyfrą.

In [28]:
table((seq(3,99,3))%%10)
0 1 2 3 4 5 6 7 8 9 
3 3 3 4 3 3 4 3 3 4 

Przekonwertuj podane temperatury w Fahrenheitach na stopnie Celsjusza fahrenheit<-c(32, 59, 86). Wzór na konwersję masz podany poniżej. $$c = \frac{(f-32)\cdot 5}{9}$$

In [29]:
fahrenheit<-c(32, 59, 86)
(fahrenheit-32)*5/9
  1. 0
  2. 15
  3. 30

Jeżeli x<-c(5,9,2,3,4,6,7,0,8,12,2,9) to co zwrócą poniższe komendy? Odpowiedz a następnie sprawdź swoje hipotezy w R.

  • x[2]
  • x[2:4]
  • x[c(2,3,6)]
  • x[c(1:5,10:12)]
  • x[-(10:12)]
In [30]:
x<-c(5,9,2,3,4,6,7,0,8,12,2,9)
x[2]
x[2:4]
x[c(2,3,6)]
x[c(1:5,10:12)]
x[-(10:12)]
9
  1. 9
  2. 2
  3. 3
  1. 9
  2. 2
  3. 6
  1. 5
  2. 9
  3. 2
  4. 3
  5. 4
  6. 12
  7. 2
  8. 9
  1. 5
  2. 9
  3. 2
  4. 3
  5. 4
  6. 6
  7. 7
  8. 0
  9. 8

Dane zawierają sprzedaż mleka w litrach dla 5 dni w 3 różnych sklepach (pierwsze 3 wartości są sprzedażą mleka w poniedziałek w kolejnych sklepach). Wygeneruj podsumowanie statystyczne sprzedaży (średnia, mediana, kwartyle) dla każdego ze sklepów.

In [31]:
y<-c(33,44,29,16,25,45,33,19,54,22,21,49,11,24,56)

W rozwiązaniu poniżej pojawiają się dwie przydatne funkcje: paste - konkatenacja ciągów znaków, domyślnie separatorem jest spacja, można to zmienić za pomocą argumentu sep oraz summary - 5-liczbowe podsumowanie (minimum, 1QR, mediana, 3QR, maksimum) + średnia

In [32]:
for (i in 1:3){
    print(paste("podsumowanie sklep",i, sep=" nr "))
    print(summary(y[seq(i,length(y), 3)]))
}
[1] "podsumowanie sklep nr 1"
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
     11      16      22      23      33      33 
[1] "podsumowanie sklep nr 2"
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   19.0    21.0    24.0    26.6    25.0    44.0 
[1] "podsumowanie sklep nr 3"
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   29.0    45.0    49.0    46.6    54.0    56.0 

Graficzna analiza danych w R

Jednym z popularnych zastosowań analizy danych w ostatnich latach jest analiza wydźwięku (ang. sentiment analysis). Firmy takie jak np. Samsung czy Apple chcąc dowiedzieć się co (nie) podoba się użytkownikom w ich produktach analizując wpisy pojawiające się na portalach takich jak Twitter czy Facebook.

Na każdym takim wpisie (,,tweecie'') dotyczącym np. nowego modelu smartfona jest przeprowadzana analiza statystyczna, która przydziela mu liczbę z pewnego zakresu np. od 1 do 10. Tę liczbę będziemy nazywać współczynnikiem wydźwięku. Wysokie wartości tego współczynnika, bliskie 10, oznaczają wpisy silnie pozytywne (,,Kocham mojego nowego Galaxy S6!!!''), a wartości niskie oznaczają wpisy niezadowolonych użytkowników (,,Co za badziew! #rozczarowanie'').

W tym ćwiczeniu będziesz pracował na właśnie takich danych, które zostały już specjalnie przetworzone i ułożone w tabelki, abyś nie musiał dokonywać żmudnych manipulacji na tekstach. Twoim zadaniem jest dokonanie graficznej analizy danych, podczas której powinieneś dowiedzieć się czego dotyczą analizowane wpisy (nie są to wpisy dot. smartfonów jak w przykładzie wyżej).

Powodzenia!

Część 1: Czego dotyczą zebrane tweety?

Na początku przygotuj twoje środowisko pracy poprzez wywołanie polecenia, które ściągnie z Internetu wszystkie potrzebne dane.

In [33]:
source("http://www.cs.put.poznan.pl/mlango/siad/data/ead.R")

Dane w R najczęściej są przechowywane w tzw. ramkach danych (data frame), która są kolekcjami wektorów (kolumn).
Jedną z załadowanych przez skrypt struktur jest ramka danych vocabulary. Sprawdźmy jej rozmiar poprzez wywołane polecenia:

In [34]:
dim(vocabulary)
  1. 32321
  2. 2

Zostały zwrócone dwie liczby: pierwsza z nich to liczba wierszy (obserwacji), a druga to liczba kolumn (atrybutów).

Dostęp do tych danych wygląda analogicznie jak do wektorów, z tym że jest to struktura dwuwymiarowa, więc trzeba podawać 2 indeksy (numer wiersza, numer kolumny). Na szczęście jeden z indeksów można pominąć -- zostanie wtedy wyświetlony cały wiersz lub cała kolumna. Na przykład aby wyświetlić piąty wiersz ramki wystarczy wpisać:

In [35]:
vocabulary[5,]
A data.frame: 1 × 2
V1V2
<fct><int>
5startup2

Zauważ, że pominęliśmy indeks kolumny w związku z czym zostały wyświetlone wszystkie kolumny piątego wiersza.

Innym sposobem na wyświetlenie większej liczby danych jest funkcja (analogiczna do Unix'owej) head(). Wywołaj ją na naszej strukturze, aby zobaczyć pierwsze pięć wierszy.

In [36]:
head(vocabulary)
A data.frame: 6 × 2
V1V2
<fct><int>
1http://t.co/dbilk9emuf1
2lana 1
3camcorder 1
4roberto 1
5startup 2
6fynn's 1

Jak pewnie się już domyślasz tabela ta zawiera słowa wraz z liczbą wystąpień we wszystkich wpisach użytkowników. Aby wyświetlić nazwy kolumn wystarczy wywołać polecenie:

In [37]:
names(vocabulary)
  1. 'V1'
  2. 'V2'

Ojej! Nazwy tych kolumn nic nam nie mówią -- pora to zmienić! Skorzystajmy z magii języka R i przypiszmy wartość do wyniku funkcji (!).

names(vocabulary) <- ...

W miejsce trzech kropek należy podać wektor nazw kolumn, w naszym przypadku dwuelementowy. Aby zachować spójność z dalej przyjętą notacją nazwij pierwszą kolumnę ,,word'', a drugą ,,count''.

In [38]:
names(vocabulary) <- c('word', 'count')

Teraz, gdy kolumny już są nazwane możemy odwoływać się do poszczególnych kolumn w sposób znacznie wygodniejszy. Na przykład aby uzyskać dostęp do całej kolumny ,,count'' możemy użyć następującej składni: vocabulary$count. Na wektorze tym możemy np.~policzyć średnią arytmetyczną:

In [39]:
mean( vocabulary$count )
5.71863494322577

Istnieją też analogiczne funkcje: max(), min(), median() czy sort(). Na~szczególną uwagę zasługuje funkcja wyświetlająca podstawowe statystyki dotyczące każdej z kolumn: summary() (możemy ją wywołać na całej ramce danych, a nie tylko na kolumnie).

In [40]:
summary(vocabulary)
        word           count         
 operating:    2   Min.   :   1.000  
          :    1   1st Qu.:   1.000  
 ^_^      :    1   Median :   1.000  
 ^-^      :    1   Mean   :   5.719  
 ~        :    1   3rd Qu.:   2.000  
 =        :    1   Max.   :7138.000  
 (Other)  :32314                     

Przystąpmy do analizy: chcielibyśmy się dowiedzieć czego dotyczą zebrane przez nas wpisy użytkowników. W tym celu sprawdźmy jak wyglądają częstotliwości występowania poszczególnych słów. Utwórz wykres słupkowy na kolumnie ,,count'' poprzez wpisanie komendy:

In [41]:
barplot(vocabulary$count, xlab="Słowo", ylab="Liczba wystąpień")

Niestety, na wykresie niezbyt wiele widać... Spróbuj posortować wartości wektora zanim utworzysz wykres. Może teraz uda Ci się wyciągnąć jakieś wnioski?

In [42]:
barplot(sort(vocabulary$count), xlab="Słowo", ylab="Liczba wystąpień")

Z wykresu wynika, że istnieje pewna mała grupa słów, które występują bardzo często w stosunku do reszty. Jeśli jakieś słowo ma dużą częstotliwość to znaczy, że wystąpiło w wielu wpisach użytkowników -- może więc dzięki nim dowiemy się czego dotyczą obserwowane przez nas wpisy? Odczytaj z wykresu wartość powyżej której występuje bardzo mała liczba słów, a następnie używając filtrowania wypisz je na ekran.

In [43]:
vocabulary[vocabulary$count>1000,]
A data.frame: 19 × 2
wordcount
<fct><int>
1017a 2699
2258for 1894
2710at 1207
5684you 1532
7456the 7138
8064i 2633
11797and 2414
16046is 1949
17061to 4152
18842may 1655
19592have1011
20375with1511
21646in 2392
23408be 1529
24424it 1313
26820on 2589
27811my 1019
29258 1576
29596of 2153

Spotkało nas rozczarowanie: większość z wyświetlonych słów nie ma żadnego realnego znaczenia, a ich częste występowanie nie niesie żadnej informacji o temacie wpisów w zbiorze danych. Na szczęście jest to znany problem w analizie tekstu, a takie słowa nazywamy z angielskiego stopwords (https://pl.wikipedia.org/wiki/Stop_lista_\%28wyszukiwarki\%29).

Wśród zmiennych w środowisku roboczym jest wektor stopwords, zawierający powszechnie używaną listę takich słów (możesz sobie ją wyświetlić).

In [44]:
stopwords
  1. ''
  2. 'a'
  3. 'able'
  4. 'about'
  5. 'across'
  6. 'after'
  7. 'all'
  8. 'almost'
  9. 'also'
  10. 'am'
  11. 'among'
  12. 'an'
  13. 'and'
  14. 'any'
  15. 'are'
  16. 'as'
  17. 'at'
  18. 'be'
  19. 'because'
  20. 'been'
  21. 'but'
  22. 'by'
  23. 'can'
  24. 'cannot'
  25. 'could'
  26. 'dear'
  27. 'did'
  28. 'do'
  29. 'does'
  30. 'either'
  31. 'else'
  32. 'ever'
  33. 'every'
  34. 'for'
  35. 'from'
  36. 'get'
  37. 'got'
  38. 'had'
  39. 'has'
  40. 'have'
  41. 'he'
  42. 'her'
  43. 'hers'
  44. 'him'
  45. 'his'
  46. 'how'
  47. 'however'
  48. 'i'
  49. 'i\'m'
  50. '-'
  51. 'if'
  52. 'in'
  53. 'into'
  54. 'is'
  55. 'it'
  56. 'its'
  57. 'just'
  58. 'least'
  59. 'let'
  60. 'like'
  61. 'likely'
  62. 'may'
  63. 'me'
  64. 'might'
  65. 'most'
  66. 'must'
  67. 'my'
  68. 'neither'
  69. 'no'
  70. 'nor'
  71. 'not'
  72. 'of'
  73. 'off'
  74. 'often'
  75. 'on'
  76. 'only'
  77. 'or'
  78. 'other'
  79. 'our'
  80. 'own'
  81. 'rather'
  82. 'said'
  83. 'say'
  84. 'says'
  85. 'she'
  86. 'should'
  87. 'since'
  88. 'so'
  89. 'some'
  90. 'than'
  91. 'that'
  92. 'the'
  93. 'their'
  94. 'them'
  95. 'then'
  96. 'there'
  97. 'these'
  98. 'they'
  99. 'this'
  100. 'tis'
  101. 'to'
  102. 'too'
  103. 'twas'
  104. 'us'
  105. 'wants'
  106. 'was'
  107. 'we'
  108. 'were'
  109. 'what'
  110. 'when'
  111. 'where'
  112. 'which'
  113. 'while'
  114. 'who'
  115. 'whom'
  116. 'why'
  117. 'will'
  118. 'with'
  119. 'would'
  120. 'yet'
  121. 'you'
  122. 'your'

Utwórz nową ramkę danych vocabulary_filtered poprzez wyfiltrowanie wszystkich wierszy zawierających stopwords. Użyj operatora %in% sprawdzającego czy wartość zmiennej występuje w zbiorze oraz operatora negacji !.

In [45]:
vocabulary_filtered <- vocabulary[!vocabulary$word %in% stopwords,]

Sprawdź poleceniem dim() czy liczba wierszy w nowej ramce jest trochę mniejsza niż w oryginalnej.

In [46]:
dim(vocabulary_filtered)
  1. 32200
  2. 2

Utwórz wykres słupkowy na nowej ramce danych (pamiętaj o posortowaniu wektora).

In [47]:
barplot(sort(vocabulary_filtered$count), xlab="Słowo", ylab="Liczba wystąpień")

Wykres szczególnie się nie zmienił, poza tym że zakres wartości jest trochę mniejszy. Jednak teraz najczęściej występujące słowa powinny być bardziej znaczące -- wyświetl je. Czy już wiesz czego dotyczą wpisy użytkowników?

In [48]:
vocabulary_filtered[vocabulary_filtered$count>700,]
A data.frame: 6 × 2
wordcount
<fct><int>
988tomorrow 795
2000linux 921
8388system 779
8392operating746
23955windows10894
30130windows 830

Teraz, gdy już wiemy, że wpisy użytkowników dotyczą odwiecznego sporu informatyków o to który system operacyjny jest najlepszy, spróbujmy sprawdzić o którym systemie użytkownicy częściej piszą oraz który system ma więcej pozytywnych wpisów.

Część 2: Który system operacyjny jest najlepszy? Linux vs Windows.

W tej części ćwiczenia będziemy analizować nową ramkę danych dostępną w zmiennej day_stats. Ramka ta zawiera 4 kolumny:

  • datę (date)
  • nazwę systemu operacyjnego (os: ,,linux'' lub ,,windows'')
  • liczbę tweetów opublikowanych w danym dniu i dotyczącego danego systemu operacyjnego (count)
  • średnią ocenę pozytywnego wydźwięku wpisów (positive_coeff) - im wyższa średnia, tym bardziej pozytywnie mówiono o danym systemie operacyjnym

Obejrzyj kilka rekordów z tabeli (funkcja head())

In [49]:
head(day_stats)
A data.frame: 6 × 4
dateoscountpositive_coeff
<date><fct><dbl><dbl>
12015-06-01linux 7797.9
22015-06-01windows8304.6
32015-06-02linux 8325.8
42015-06-02windows8649.8
52015-06-03linux 7936.8
62015-06-03windows8977.2

Wyświetl podsumowanie informacji o tych danych (summary()). Z jakiego okresu czasu pochodzą dane? Jaka jest średni współczynnik pozytywnego wydźwięku analizowanych wpisów?

In [50]:
summary(day_stats)
      date                  os         count        positive_coeff 
 Min.   :2015-06-01   linux  :90   Min.   : 700.0   Min.   :2.600  
 1st Qu.:2015-06-23   windows:90   1st Qu.: 750.5   1st Qu.:6.275  
 Median :2015-07-15                Median : 804.5   Median :7.200  
 Mean   :2015-07-15                Mean   : 881.1   Mean   :7.149  
 3rd Qu.:2015-08-07                3rd Qu.: 865.0   3rd Qu.:8.200  
 Max.   :2015-08-29                Max.   :4600.0   Max.   :9.900  

W celu dokładniejszego zbadania wartości współczynnika wydźwięku skonstruujmy dla niego histogram:

In [51]:
hist(day_stats$positive_coeff, main="", xlab="Ocena wydźwięku", ylab="Liczność")

Chcielibyśmy uzyskać histogram z większą liczbą słupków oraz z słupkami pokolorowanymi na czerwono ("red"). Korzystając z pomocy do funkcji hist (aby ją wyświetlić wpisz znak zapytania i nazwę funkcji) zbuduj takie histogramy dla liczby słupków 70 i 150.

In [52]:
?hist

Histogram mający 70 słupków

In [53]:
hist(day_stats$positive_coeff, breaks = 70, col="red", main="", xlab="Ocena wydźwięku", ylab="Liczność")

Histogram mający 150 słupków

In [54]:
hist(day_stats$positive_coeff, breaks = 150, col="red", main="", xlab="Ocena wydźwięku", ylab="Liczność")

Obraz histogramu przy 150 słupkach jest ,,szarpany'' (raz słupek raz wolne miejsce). Dlaczego się tak stało? Aby odpowiedzieć na to pytanie zobacz do ilu miejsc po przecinku są raportowe współczynniki wydźwięku i jaki jest ich zakres wartości.

In [55]:
summary(day_stats$positive_coeff)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  2.600   6.275   7.200   7.149   8.200   9.900 

Jaka jest szerokość przedziału, który obejmuje jeden słupek na wykresie?

In [56]:
(9.9-2.6)/150
0.0486666666666667

Jak sądzisz czy ten histogram ze 150 słupkami jest prawidłowy?

Innym sposobem zobaczenia rozkładu wartości (z mniejszą szczegółowością) jest narysowanie wykresu pudełkowego. Narysuj go w R poprzez wywołanie funkcji boxplot().

In [57]:
boxplot(day_stats$positive_coeff, ylab="Ocena wydźwięku")

Pewną zaletą wykresu pudełkowego nad histogramem jest to, że na jednym wykresie możemy zaprezentować kilka serii wartości. Chcielibyśmy się dowiedzieć jak różni się rozkład współczynnika wydźwięku dla różnych systemów operacyjnych. Aby to zrobić narysujmy wykres pudełkowy współczynnika wydźwięku w zależności od zmiennej system operacyjny.

boxplot(day_stats$positive_coeff ~ day_stats$os)

Wyrażenia typu y~x możesz czytać jako ,,y zależy od x'', ,,y jako funkcja od x''...

In [58]:
boxplot(day_stats$positive_coeff ~ day_stats$os, ylab="Ocena wydźwięku")

O którym systemie operacyjnym użytkownicy piszą pozytywniej? Czy możesz wyciągnąć z wykresu jakieś inne wnioski?

Kończąc naszą analizę sprawdźmy czy są dni w których użytkownicy piszą częściej o którymś z systemów operacyjnych np.~o~systemie Linux. W tym celu utwórzmy nową ramkę zawierającą tylko dane o systemie Linux:

In [59]:
day_stats_linux <- day_stats[day_stats$os == 'linux',]

A następnie użyj funkcji plot() do narysowania wykresu liczby tweetów w czasie. Argumentem tej funkcji powinno być wyrażenie ,,liczba wpisów zależy od daty'' (konstrukcja z operatorem ~).

In [60]:
plot(day_stats_linux$count ~ day_stats_linux$date, xlab="Data", ylab="Liczba tweetów")

Otrzymaliśmy wykres punktowy, a chcielibyśmy otrzymać wykres liniowy. Korzystając z pomocy pakietu R znajdź dodatkowy argument funkcji plot(), który spowoduje utworzenie porządanego typu wykresu.

In [61]:
plot(day_stats_linux$count ~ day_stats_linux$date, t="l", xlab="Data", ylab="Liczba tweetów")

Wygląda na to, że liczba wpisów o systemie Linux waha się pomiędzy kolejnymi dniami, ale nie widzimy żadnego trendu tj.~liczba wpisów nie rośnie ani nie maleje. Spróbuj zbudować analogiczny wykres dla systemu Windows -- może tam zobaczysz coś ciekawego?

In [62]:
day_stats_windows<- day_stats[day_stats$os == 'windows',]
plot(day_stats_windows$count ~ day_stats_windows$date, t="l", xlab="Data", ylab="Liczba tweetów")

Korzystając z internetu spróbuj znaleźć przyczynę, która spowodowała nagły wzrost tweetów dotyczących systemu Windows w drugiej połowie sierpnia 2015?.

Ćwiczenia

Behavioral Risk Factor Surveillance System (BRFSS) to doroczna ankieta telefoniczna przeprowadzana w Stanach Zjednoczonych mająca na celu zidentyfikowanie i kontrolowanie zagrożeń zdrowotnych w populacji ludzi dorosłych. Respondenci udzielają odpowiedzi na pytania dotyczące ich diety, cotygodniowej aktywności fizycznej, użycia papierosów, chorowania na HIV/AIDS itd. (Pełen opis tego badania możesz znaleźć na stornie http://www.cdc.gov/brfss). Losowa próbka 20 tysięcy obserwacji z tego badania jest dostępna w zmiennej medical_data.

Przeprowadź graficzną analizę tych danych, a w szczególności:

  • narysuj wykres słupkowy pokazujący liczbę osób palących i nie palących (kolumna ,,smoke100'' zawiera odpowiednio ,,0'' lub ,,1'' gdy ktoś pali lub nie). Podpisz osie wykresu.

Wskazówka: Do konstrukcji tabeli częstości występowania wartości zmiennej można wykorzystać funkcję table()

Wykres słupkowy - funkcja barplot

In [63]:
barplot(table(medical_data$smoke100), ylab = "Liczba osób", 
   xlab = "Palenie", names.arg = c("Nie", "Tak"))
  • narysuj wykres pudełkowy wysokości człowieka (height) w zależności od płci (gender).
In [64]:
boxplot(medical_data$height ~ medical_data$gender, xlab="Płeć", ylab="Wzrost [cale]", names=c("Mężczyzna", "Kobieta"))
  • używając wykresu pudełkowego sprawdź zależność pomiędzy ogólną oceną stanu zdrowia (genhlth) a wskaźnikiem masy ciała BMI (patrz: https://pl.wikipedia.org/wiki/Wska\%C5\%BAnik_masy_cia\%C5\%82a), który (biorąc pod uwagę jednostki użyte do mierzenia wysokości i wagi w zbiorze danych) można wyrazić wzorem: $$BMI=\frac{weigth}{height^2} \cdot 703 $$
    Zdrowy człowiek powinien mieć BMI pomiędzy 18.5 a 25.
In [65]:
bmi <- (medical_data$weight / medical_data$height^2) * 703
boxplot(bmi ~ medical_data$genhlth, xlab="Stan zdrowia", ylab="BMI")
  • narysuj histogram wieku badanych (age)
In [66]:
hist(medical_data$age, xlab="Wiek", ylab="Liczność")
  • zbadaj zależność pomiędzy płcią (gender) oraz różnicą pomiędzy pożądaną wagą (wtdesire) a wagą aktualną (weight).
In [67]:
wdiff<- medical_data$wtdesire - medical_data$weight
boxplot(wdiff~medical_data$gender, xlab="Płeć", ylab="wtdesire-weight", names=c("Mężczyzna", "Kobieta"))
In [68]:
boxplot(wdiff~medical_data$gender, ylim=c(-200, 100), xlab="Płeć", ylab="wtdesire-weight", names=c("Mężczyzna", "Kobieta"))