בפרקים הקודמים כבר נגענו בפקודות שונות, וקצת בתכנות ב-R, אך בפרק הזה נציג את יסודות התכנות ב-R באופן מסודר.

כשמעלים את RStudio, אז מופיע בצד התחתון שלו ה-Console. בחלק זה ניתן להריץ קוד כמו “מחשבון”. לדוגמה:

cos(2*pi)
## [1] 1
log(10^5)
## [1] 11.51293
log10(10^5)
## [1] 5
sqrt(144)
## [1] 12
12^2
## [1] 144

ניתן ליצור אובייקטים חדשים עם אופרטור ההשמה ->, באופן הבא:

foo <- "bar"
foo
## [1] "bar"
bar <- 99*111
bar
## [1] 10989

איך קובעים שמות ב-R?

שמות משתנים חייבים להתחיל באות (גדולה או קטנה), ויכולים להכיל אותיות, מספרים, קו תחתון _ ונקודה.. כדי לבנות משתנים ששמם הוא בעל משמעות, לעיתים תידרש יותר ממילה אחת, לשם כך מומלץ להפריד עם _.

R הוא רגיש לאותיות קטנות וגדולות (case sensitive), בדרך כלל מקובל להשתמש באותיות קטנות בלבד.

הרצות לדוגמה (מה-console, לכן מופיע התו “<” בתחילת שורה. כדי להריץ את הקוד השמיטו תו זה.


> short_name <- 3
> long_description <- "This is a description of foo bar"

> r_is_great <- 10
> r_is_great

> r_is_great
[1] 10
> R_is_great
Error: object 'R_is_great' not found

שימוש בפונקציות

ל-R יש פונקציות מובנות, ופונקציות הנמצאות בתוך חבילות. קריאה לפונקציה מתבצעת באופן הבא:


function_name(arg1 = val1, arg2 = val2, ...)

אם הפונקציה אינה ב-Base R אז ראשית צריך לטעון את החבילה באחד משני האופנים הבאים:

# either do this
package_name::function_name(...)

# or first load, then use freely
library(package_name)
function_name(...)

תרגיל

  1. נסו לתקן ולהריץ את הקוד הבא. מומלץ לנסות ולהריץ אותו ב-console שלב אחרי שלב כדי לבדוק מה לא עובד…
library(tidyvers)

glimpse(iris)

ggplot(data = iris) + 
  geom_point(aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  + geom_smooth(method = "lm")

fliter(iris, Species = "setosa")



תחביר ב-R

ב-Cheat sheet הבא מפורטים שלושה סוגים של תחבירים (syntax.pdf): https://github.com/rstudio/cheatsheets/raw/master/syntax.pdf

במהלך הקורס ניתן דגש לתחביר Tidyverse, אך מומלץ להכיר גם את התחבירים האחרים. לדוגמה, חישוב ממוצע בתחביר הבסיסי ובתחביר Tidyverse יראה כך:

# base R syntax:
# calculate average
mean(mtcars$mpg)
## [1] 20.09062
# average vs. discrete var
mean(mtcars$mpg[mtcars$cyl==4])
## [1] 26.66364
mean(mtcars$mpg[mtcars$cyl==6])
## [1] 19.74286
mean(mtcars$mpg[mtcars$cyl==8])
## [1] 15.1
# plot histogram
hist(mtcars$disp)

# subsetting
mtcars[mtcars$mpg > 30,]
##                 mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Fiat 128       32.4   4 78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic    30.4   4 75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla 33.9   4 71.1  65 4.22 1.835 19.90  1  1    4    1
## Lotus Europa   30.4   4 95.1 113 3.77 1.513 16.90  1  1    5    2
# Tidyverse syntax
library(tidyverse)

# calculate average
mtcars %>%
  summarize(mean(mpg))
##   mean(mpg)
## 1  20.09062
# average vs. discrete var
mtcars %>%
  group_by(cyl) %>%
  summarize(mean(mpg))
## # A tibble: 3 x 2
##     cyl `mean(mpg)`
##   <dbl>       <dbl>
## 1     4        26.7
## 2     6        19.7
## 3     8        15.1
# plot histogram
ggplot(mtcars, aes(x=disp)) + geom_histogram()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

# subsetting
mtcars %>% filter(mpg > 30)
##    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## 1 32.4   4 78.7  66 4.08 2.200 19.47  1  1    4    1
## 2 30.4   4 75.7  52 4.93 1.615 18.52  1  1    4    2
## 3 33.9   4 71.1  65 4.22 1.835 19.90  1  1    4    1
## 4 30.4   4 95.1 113 3.77 1.513 16.90  1  1    5    2

סוגי מבנה נתונים ב-R

משתנה ב-R יכול לקבל ערכים ממספר סוגים, העיקריים שבהם:

שימו לב שהשמה נראית כחץ -> (בעדיפות) או כשיוויון =

לדוגמה:

integer_example <- 10
integer_example
## [1] 10
numeric_example <- pi # pi is a reserved word...
numeric_example
## [1] 3.141593
character_examples <- "hello world"
character_examples
## [1] "hello world"
date_example <- as.Date("2018-10-01")
date_example
## [1] "2018-10-01"
factor_example <- as.factor(c("big", "big", "small", "medium", "small", "big", "bigger"))
factor_example
## [1] big    big    small  medium small  big    bigger
## Levels: big bigger medium small
summary(factor_example)
##    big bigger medium  small 
##      3      1      1      2
logical_example <- c(TRUE, TRUE, FALSE, TRUE)
logical_example
## [1]  TRUE  TRUE FALSE  TRUE

בעצם כל האובייקים ב-R הם מערכים (גם אם יש בהם רק ערך אחד, הם עדיין מערכים ולא סקלר). דוגמאות:

int_vector <- 1:10
int_vector
##  [1]  1  2  3  4  5  6  7  8  9 10
dbl_vector <- c(1, pi, 3.3, sqrt(2)/2)
dbl_vector
## [1] 1.0000000 3.1415927 3.3000000 0.7071068
chr_vector <- c("hello", "world", 1, pi) # see that the numbers are type cast-ed into characters
chr_vector
## [1] "hello"            "world"            "1"               
## [4] "3.14159265358979"
cbind(1:10, 21:30, 41:50)
##       [,1] [,2] [,3]
##  [1,]    1   21   41
##  [2,]    2   22   42
##  [3,]    3   23   43
##  [4,]    4   24   44
##  [5,]    5   25   45
##  [6,]    6   26   46
##  [7,]    7   27   47
##  [8,]    8   28   48
##  [9,]    9   29   49
## [10,]   10   30   50
# the following is a data frame:
df_example <- data.frame(city = c("Jerusalem", "Tel-Aviv", "Haifa", "Rishon LeTzion"), 
                         order_population = c(1, 2, 3, 4))
df_example
##             city order_population
## 1      Jerusalem                1
## 2       Tel-Aviv                2
## 3          Haifa                3
## 4 Rishon LeTzion                4
# another example
mtcars
##                      mpg cyl  disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4           21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag       21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710          22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive      21.4   6 258.0 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout   18.7   8 360.0 175 3.15 3.440 17.02  0  0    3    2
## Valiant             18.1   6 225.0 105 2.76 3.460 20.22  1  0    3    1
## Duster 360          14.3   8 360.0 245 3.21 3.570 15.84  0  0    3    4
## Merc 240D           24.4   4 146.7  62 3.69 3.190 20.00  1  0    4    2
## Merc 230            22.8   4 140.8  95 3.92 3.150 22.90  1  0    4    2
## Merc 280            19.2   6 167.6 123 3.92 3.440 18.30  1  0    4    4
## Merc 280C           17.8   6 167.6 123 3.92 3.440 18.90  1  0    4    4
## Merc 450SE          16.4   8 275.8 180 3.07 4.070 17.40  0  0    3    3
## Merc 450SL          17.3   8 275.8 180 3.07 3.730 17.60  0  0    3    3
## Merc 450SLC         15.2   8 275.8 180 3.07 3.780 18.00  0  0    3    3
## Cadillac Fleetwood  10.4   8 472.0 205 2.93 5.250 17.98  0  0    3    4
## Lincoln Continental 10.4   8 460.0 215 3.00 5.424 17.82  0  0    3    4
## Chrysler Imperial   14.7   8 440.0 230 3.23 5.345 17.42  0  0    3    4
## Fiat 128            32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
## Honda Civic         30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
## Toyota Corolla      33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
## Toyota Corona       21.5   4 120.1  97 3.70 2.465 20.01  1  0    3    1
## Dodge Challenger    15.5   8 318.0 150 2.76 3.520 16.87  0  0    3    2
## AMC Javelin         15.2   8 304.0 150 3.15 3.435 17.30  0  0    3    2
## Camaro Z28          13.3   8 350.0 245 3.73 3.840 15.41  0  0    3    4
## Pontiac Firebird    19.2   8 400.0 175 3.08 3.845 17.05  0  0    3    2
## Fiat X1-9           27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
## Porsche 914-2       26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
## Lotus Europa        30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
## Ford Pantera L      15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
## Ferrari Dino        19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
## Maserati Bora       15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
## Volvo 142E          21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2
# a list can contain any combination of arrays, data frames, and lists
list(int_vector, dbl_vector, chr_vector, df_example)
## [[1]]
##  [1]  1  2  3  4  5  6  7  8  9 10
## 
## [[2]]
## [1] 1.0000000 3.1415927 3.3000000 0.7071068
## 
## [[3]]
## [1] "hello"            "world"            "1"               
## [4] "3.14159265358979"
## 
## [[4]]
##             city order_population
## 1      Jerusalem                1
## 2       Tel-Aviv                2
## 3          Haifa                3
## 4 Rishon LeTzion                4

כדי לפנות לאיבר מסוים בתוך וקטור משתמשים בסוגריים מרובעים [], לדוגמה

dbl_vector[1:3]
## [1] 1.000000 3.141593 3.300000

פעולות אריתמטיות

פעולות אריתמטיות עובדות על משתנים ומערכים כל עוד גודלם תואם (והסוג שלהם מאפשר פעולות אלו)

c(1, pi, 3.3, sqrt(2)/2)^2
## [1]  1.000000  9.869604 10.890000  0.500000
#c("hello", "world", 1, pi) + 1 # yields an error - you can't add 1 to a character
> c("hello", "world", 1, pi) + 1
Error in c("hello", "world", 1, pi) + 1 : 
  non-numeric argument to binary operator

לולאות, אופרטורים, והתניות

בדרך כלל, מומלץ להימנע ככל שניתן מלולאות. חלק גדול מהפעולות ב-R פועלות באופן וקטורי או מטריציוני. לולאת for בנוייה מהתבנית הבאה:

for (i in vector){
   # the action that needs to be done...
}

תרגול

שימוש בלולאות לעומת פעולות וקטוריות.

  1. הגדר וקטור של כל המספרים הזוגיים בין 1-10000000. באפשרותך להיעזר בפונקציה seq. כדי ללמוד על הפונקציה הקש ב-console:
?seq
  1. האם יש דרך אחרת להגדיר את הוקטור מבלי להשתמש בפונקציה seq?
  2. חשב וקטור חדש שהוא הוקטור שקיבלת בריבוע, בשתי דרכים שונות:
    1. באמצעות לולאת for
    2. באמצעות פעולה וקטורית
  3. השתמש בפונקציה Sys.time כדי למדוד את משך הזמן שנדרש לשתי הפעולות

אופרטורים לוגיים ב-R:

  • או |
  • וגם &
  • not !
  • xor(a,b)
  • בדיקת שיוויון ==
  • שונה !=
5 == 6
## [1] FALSE
6 == 6
## [1] TRUE
5 == 6 | 6 == 6
## [1] TRUE
Inf > 10^10
## [1] TRUE
TRUE & FALSE
## [1] FALSE
xor(TRUE, FALSE)
## [1] TRUE
FALSE == !TRUE
## [1] TRUE
FALSE != TRUE
## [1] TRUE

תרגיל - השוואות

  1. מדוע השיוויון הבא נכשל?
  2. מדוע הפונקציה near עובדת?
x <- sqrt(2)^2

x == 2
## [1] FALSE
dplyr::near(sqrt(2)^2, 2)
## [1] TRUE

ערכים חסרים

בסטטיסטיקה, לעיתים קרובות ישנם “ערכים חסרים”, תצפיות שלא נמדדו או לא תועדו. ב-R, ערכים אלו מיוצגים על ידי NA.


תרגול NA

  1. בדקו את תוצאת הפעולות הבאות:
NA+0
NA*1
NA^0
NA | TRUE
NA & FALSE
NA*0
  1. האם אתם מצליחים להבין את ההיגיון מאחורי תוצאות החישובים הללו?

התניות

if (condition){
   expression
} else if (condition){
   expression
} else {
   expression
}

בשלבים הראשוניים של עבודה עם R מומלץ להיעזר ב-Cheat sheet של “base-r.pdf” בקישור: http://github.com/rstudio/cheatsheets/raw/master/base-r.pdf

חבילות הרחבה

מעבר לפקודות הבסיסיות שנקראות “Base R”, ישנן חבילות רבות שמעשירות את R. מה שהופך את R לשפה מאוד אטרקטיבית משום שלהרבה מהצרכים שבהם אתם עשויים להיתקל, כבר פותחו פתרונות.

בפרק הבא

בפרק הבא נעמיק בחבילות חשובות המשמשות לעיבוד נתונים ברמה הבסיסית (סינונים, טרנספורמציות, וכו’)