هذا العمل هو تلخيص وترجمه للباب الثاني (Wrangle) من كتاب R for Data Science للكاتبين Hadly Wickham و Garrett Grolemund مع بعض الاضافات

ترتيب المقاله كالتالي

1- Tibbles.

2- Data import.‬

‬ 3- Tidy data.

تحتاج في البداية ان تقوم بتحميل مكتبة tidyverse

library(tidyverse)

Tibbles


في هذا القسم راح تتعلم

1- الفرق بين tibble و data.fram

2- إنشاء جدول جديد

3- طباعة الجدول

4- Subsetting

خلال هذة المقاله سوف نستعمل ()tibble بدلا هن الدالة التقليدية ()data.frame

للتحويل من ()data.frame الى ()tibbles نستخدم

as_tibble(iris)
## # A tibble: 150 x 5
##    Sepal.Length Sepal.Width Petal.Length Petal.Width Species
##           <dbl>       <dbl>        <dbl>       <dbl> <fct>  
##  1          5.1         3.5          1.4         0.2 setosa 
##  2          4.9         3            1.4         0.2 setosa 
##  3          4.7         3.2          1.3         0.2 setosa 
##  4          4.6         3.1          1.5         0.2 setosa 
##  5          5           3.6          1.4         0.2 setosa 
##  6          5.4         3.9          1.7         0.4 setosa 
##  7          4.6         3.4          1.4         0.3 setosa 
##  8          5           3.4          1.5         0.2 setosa 
##  9          4.4         2.9          1.4         0.2 setosa 
## 10          4.9         3.1          1.5         0.1 setosa 
## # … with 140 more rows

ملاحظه: عند استخدام عند استعمالك ()readr::read_csv فإن الناتج يكون tibble لاكن عند استعمال ()base::read.csv فإن الناتج يكون data.frame

الفرق بين tibble و data.frame

data.frame هي الصيغة الاساس لحفظ الجداول في R. مؤخرا قام كل من Kirill Müller و Hadley Wickham بتعديل واضافة بعض المزايا الجديدة الى data.frame واطلقو عليه اسم tibble

اذا tibble ليس الا تحديث ل data.frame

1- طريقة عرض البيانات في Console

data_14_tibble<-read_csv("data/data14.csv")
## Parsed with column specification:
## cols(
##   id = col_double(),
##   Gender = col_character(),
##   Age = col_double(),
##   `Education level` = col_character(),
##   `Marital status` = col_character(),
##   City = col_character(),
##   `Family member` = col_double(),
##   Salary = col_double(),
##   `Monthly rent` = col_double()
## )
data_14_data.frame <- read.csv("data/data14.csv")

لاحظ ان ()read_csv من tibble أظهرت لنا type كل عمود بينما ()read.csv من base R لم تظهر لنا شيء

glimpse(data_14_tibble)
## Rows: 200
## Columns: 9
## $ id                <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, …
## $ Gender            <chr> "Female", "Female", "Female", "Female", "Female", "…
## $ Age               <dbl> 32, 33, 34, 32, 27, 41, 32, 25, 33, 28, 28, 35, 30,…
## $ `Education level` <chr> "B.Sc", "B.Sc", "B.Sc", "B.Sc", "B.Sc", "PhD", "B.S…
## $ `Marital status`  <chr> "Single", "Married", "Married", "Married", "Married…
## $ City              <chr> "Riyadh", "Riyadh", "Jeddah", "Dammam", "Dammam", "…
## $ `Family member`   <dbl> 1, 4, 3, 5, 4, 2, 6, 3, 3, 2, 3, 1, 5, 1, 2, 1, 4, …
## $ Salary            <dbl> 12645, 12448, 12391, 8863, 12863, 22334, 11787, NA,…
## $ `Monthly rent`    <dbl> 2528, 2384, 2059, 1848, 2526, 4112, 1989, 1899, 242…
glimpse(data_14_data.frame)
## Rows: 200
## Columns: 9
## $ id              <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16…
## $ Gender          <fct> Female, Female, Female, Female, Female, Female, Male,…
## $ Age             <int> 32, 33, 34, 32, 27, 41, 32, 25, 33, 28, 28, 35, 30, 2…
## $ Education.level <fct> B.Sc, B.Sc, B.Sc, B.Sc, B.Sc, PhD, B.Sc, B.Sc, B.Sc, …
## $ Marital.status  <fct> Single, Married, Married, Married, Married, Married, …
## $ City            <fct> Riyadh, Riyadh, Jeddah, Dammam, Dammam, Riyadh, Jedda…
## $ Family.member   <int> 1, 4, 3, 5, 4, 2, 6, 3, 3, 2, 3, 1, 5, 1, 2, 1, 4, 4,…
## $ Salary          <int> 12645, 12448, 12391, 8863, 12863, 22334, 11787, NA, 1…
## $ Monthly.rent    <int> 2528, 2384, 2059, 1848, 2526, 4112, 1989, 1899, 2423,…

لاحظ ايضا اختلاف ال type بين المتغيرات الاسمية والرقمية

2- استعمال [[]] مع tibble و data.fram

# يعطينا vector
class(data_14_data.frame[ , 1])
## [1] "integer"
# يعطينا tibble
class(data_14_tibble[ , 1])
## [1] "tbl_df"     "tbl"        "data.frame"
# يعطينا vector
class(data_14_tibble %>% pull(id))
## [1] "numeric"

استخراج عمود من data.frame يعطينا دائما vector بينما tibble يعطينا دائما tibble

3- استخدام list مع tibble و data.frame

تخيل لسبب ما انك تريد اضافه معلمات اضفية لكل صف. مثلا لنفرض انك قمت ب اختبار علاج على ثلاث مجموعات من الناس

وتريد حفظ بيانات كل مجموعة في صف

a = tibble(age = sample(20:50, 5),
           name = letters[1:5])

b = tibble(age = sample(20:50, 5),
           name = letters[6:10])

c = tibble(age = sample(20:50, 5),
           name = letters[11:15])

tibble(group = c("a","b","c"), data= list(a,b,c))
## # A tibble: 3 x 2
##   group data            
##   <chr> <list>          
## 1 a     <tibble [5 × 2]>
## 2 b     <tibble [5 × 2]>
## 3 c     <tibble [5 × 2]>
data.frame(group = c("a","b","c"), data = list(a,b,c))
## Error in data.frame(group = c("a", "b", "c"), data = list(a, b, c)): arguments imply differing number of rows: 3, 5

لاحظ انه مع tibble نستطيع اضافة list في خلية لاكن لانستطيع عمل نفس الشيء مع data.fram

ربما يكون هذا مفيدا اذا اردنا عمل model لكل مدينة في هذا الجدول مثلا

library(purrr)

data_14_tibble
## # A tibble: 200 x 9
##       id Gender   Age `Education leve… `Marital status` City  `Family member`
##    <dbl> <chr>  <dbl> <chr>            <chr>            <chr>           <dbl>
##  1     1 Female    32 B.Sc             Single           Riya…               1
##  2     2 Female    33 B.Sc             Married          Riya…               4
##  3     3 Female    34 B.Sc             Married          Jedd…               3
##  4     4 Female    32 B.Sc             Married          Damm…               5
##  5     5 Female    27 B.Sc             Married          Damm…               4
##  6     6 Female    41 PhD              Married          Riya…               2
##  7     7 Male      32 B.Sc             Married          Jedd…               6
##  8     8 Female    25 B.Sc             Married          Riya…               3
##  9     9 Male      33 B.Sc             Married          Riya…               3
## 10    10 Female    28 M.Sc             Married          Jedd…               2
## # … with 190 more rows, and 2 more variables: Salary <dbl>, `Monthly
## #   rent` <dbl>
data_14_tibble_by_city<-data_14_tibble %>%
  na.omit() %>% 
  select(-id) %>%
  group_by(City) %>% 
  nest()

data_14_tibble_by_city
## # A tibble: 3 x 2
## # Groups:   City [3]
##   City   data              
##   <chr>  <list>            
## 1 Riyadh <tibble [110 × 7]>
## 2 Jeddah <tibble [44 × 7]> 
## 3 Dammam <tibble [41 × 7]>
# function لحساب الانحدار الخطي
data_lm <- function(data){
  lm(`Monthly rent` ~ ., data = data)
}

data_14_tibble_by_city<-data_14_tibble_by_city %>%
  mutate(model  = map(data, data_lm))

data_14_tibble_by_city
## # A tibble: 3 x 3
## # Groups:   City [3]
##   City   data               model 
##   <chr>  <list>             <list>
## 1 Riyadh <tibble [110 × 7]> <lm>  
## 2 Jeddah <tibble [44 × 7]>  <lm>  
## 3 Dammam <tibble [41 × 7]>  <lm>
# 
map(data_14_tibble_by_city$model, summary)
## [[1]]
## 
## Call:
## lm(formula = `Monthly rent` ~ ., data = data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -230.62  -66.47    2.82   59.05  263.08 
## 
## Coefficients:
##                          Estimate Std. Error t value Pr(>|t|)    
## (Intercept)            -7.066e+02  8.443e+01  -8.369 3.22e-13 ***
## GenderMale              3.178e+01  1.752e+01   1.814   0.0726 .  
## Age                     1.167e+01  2.836e+00   4.115 7.86e-05 ***
## `Education level`M.Sc  -2.640e+02  2.621e+01 -10.072  < 2e-16 ***
## `Education level`PhD   -8.119e+02  4.776e+01 -17.000  < 2e-16 ***
## `Marital status`Single  6.354e+00  2.962e+01   0.215   0.8306    
## `Family member`         9.038e+00  7.152e+00   1.264   0.2092    
## Salary                  2.224e-01  1.585e-03 140.318  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 90.03 on 102 degrees of freedom
## Multiple R-squared:  0.9975, Adjusted R-squared:  0.9973 
## F-statistic:  5712 on 7 and 102 DF,  p-value: < 2.2e-16
## 
## 
## [[2]]
## 
## Call:
## lm(formula = `Monthly rent` ~ ., data = data)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -0.51244 -0.22112 -0.00874  0.23636  0.50992 
## 
## Coefficients:
##                          Estimate Std. Error  t value Pr(>|t|)    
## (Intercept)             8.055e-01  4.855e-01    1.659    0.106    
## GenderMale             -6.668e-02  9.754e-02   -0.684    0.499    
## Age                     4.987e+00  1.356e-02  367.860   <2e-16 ***
## `Education level`M.Sc  -4.471e-03  1.589e-01   -0.028    0.978    
## `Education level`PhD    7.888e-02  2.902e-01    0.272    0.787    
## `Marital status`Single  8.546e-02  1.602e-01    0.533    0.597    
## `Family member`         1.003e+01  4.409e-02  227.552   <2e-16 ***
## Salary                  1.500e-01  1.807e-05 8301.987   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3084 on 36 degrees of freedom
## Multiple R-squared:      1,  Adjusted R-squared:      1 
## F-statistic: 4.114e+07 on 7 and 36 DF,  p-value: < 2.2e-16
## 
## 
## [[3]]
## 
## Call:
## lm(formula = `Monthly rent` ~ ., data = data)
## 
## Residuals:
##     Min      1Q  Median      3Q     Max 
## -0.5433 -0.2215  0.0000  0.1703  0.4576 
## 
## Coefficients:
##                          Estimate Std. Error  t value Pr(>|t|)    
## (Intercept)             9.242e-01  6.036e-01    1.531    0.135    
## GenderMale             -2.882e-02  1.164e-01   -0.248    0.806    
## Age                     5.998e+00  1.803e-02  332.629   <2e-16 ***
## `Education level`M.Sc  -3.317e-02  2.057e-01   -0.161    0.873    
## `Education level`PhD    2.348e-01  4.980e-01    0.471    0.640    
## `Marital status`Single  7.266e-02  1.685e-01    0.431    0.669    
## `Family member`         1.199e+01  4.373e-02  274.176   <2e-16 ***
## Salary                  1.800e-01  3.023e-05 5953.170   <2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.3032 on 33 degrees of freedom
## Multiple R-squared:      1,  Adjusted R-squared:      1 
## F-statistic: 1.76e+07 on 7 and 33 DF,  p-value: < 2.2e-16

Education level طلع مؤثر في البيانات تبع الرياض دون باقي المدن

إنشاء جدول جديد

يمكنك انشاء جدول عن طريق ()tibble

tibble(
  x = 1:5, 
  y = 1, 
  z = x ^ 2 + y
)
## # A tibble: 5 x 3
##       x     y     z
##   <int> <dbl> <dbl>
## 1     1     1     2
## 2     2     1     5
## 3     3     1    10
## 4     4     1    17
## 5     5     1    26

لاحظ ان ()tibble تتكفل بإكمال القيم في حاله ان قيمه الادخال كانت رقم واحد

.ايضا لاحظ انه بمكاننا استخدام المتغيرات التي قمنا بانشائها

.طباعه الجدول

بامكانك استخدام ()View وهي built-in from Rstudio

library(nycflights13)

flights %>% 
  View()

او ()print

flights %>% 
  print(n = 10, width = Inf)

( n جرب قيم اخرى مع )

Subsetting

لاستخراج متغير من (عمود) من الجدول استخدم $ او ]]

df <- tibble(
  x = runif(5),
  y = rnorm(5)
)

# Extract by name
# استخراج بالاسم

df$x
## [1] 0.7502283 0.4065100 0.5655887 0.6851015 0.2545765
df[["x"]]
## [1] 0.7502283 0.4065100 0.5655887 0.6851015 0.2545765
# Extract by position
# استخراج بالموقع

df[[1]]
## [1] 0.7502283 0.4065100 0.5655887 0.6851015 0.2545765

او اذا اردت يمكنك استخدام ال pipe (%>%) لاكن يجب عليك استخدام .

df %>% .$x
## [1] 0.7502283 0.4065100 0.5655887 0.6851015 0.2545765
df %>% .[["x"]]
## [1] 0.7502283 0.4065100 0.5655887 0.6851015 0.2545765

ماهو ال pipe %>%

تم تطوير pipe عن طريق Stefan Milton Bache في مكتبة magrittr لاكن تم تضمينه مع tidyverse

الهدف منه هو مساعدتك في كتابة الكود بطريقة يسهل قرائتها

من شروط ال pipe ان ياخذ اول argument جدول او vector

لاكن بسبب ان هناك الكثير من ال functions لاتاخذ الجدول او ال vector كأول argumnet نستخدم النقطه التي تساعدنا في التحكم بال pipe.

df %>% head(.)
## # A tibble: 5 x 2
##       x      y
##   <dbl>  <dbl>
## 1 0.750  0.738
## 2 0.407 -1.95 
## 3 0.566 -0.737
## 4 0.685 -1.19 
## 5 0.255 -1.52
df %>% head()
## # A tibble: 5 x 2
##       x      y
##   <dbl>  <dbl>
## 1 0.750  0.738
## 2 0.407 -1.95 
## 3 0.566 -0.737
## 4 0.685 -1.19 
## 5 0.255 -1.52
df %>% lm(x ~ y )
## Error in as.data.frame.default(data): cannot coerce class '"formula"' to a data.frame
df %>% lm(x ~ y, data = . )
## 
## Call:
## lm(formula = x ~ y, data = .)
## 
## Coefficients:
## (Intercept)            y  
##      0.6678       0.1455

Data Import

في هذا القسم راح تتعلم كيف تقراء الملفات بمختلف الصيغ في R

  • ()read_csv يقراء الملفات التي يكون الفاصل بين كل عمود فيها فاصله “،”

  • ()read_csv2 يقرا الملفات التي يكون الفاصل بين كل عمود فيها علامه الفاصلة المنقوطه “;”

  • ()read_tsv يقراء الملفات التي يكون الفاصل بين كل عمود فيها tap ,

  • ()read_table يقرا الملفات التي يكون الفاصل بين كل عمود فيها مسافه ,

  • ()read_fwf + يقرا الملفات التي تكون فيها المسافه بين كل عمود غير محددة وتختلف من عمود لآخر ,

  • ()read_log تقرا ملفات Apach style log ,

كل ماتحتاجة لقراءة اي ملف هو تحديد مكان الملف.

heights <- read_csv("data/heights.csv")

.بالامكان ايضا قراءه المدخلات مباشره

read_csv("a,b,c
1,2,3
4,5,6")
## # A tibble: 2 x 3
##       a     b     c
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     6

في الحالتين السابقتين ()read_csv تستخدم الصف الاول كاسماء للاعمده لاكن احيانا قد لايكون الصف الاول مهما

لنتجاوز السطر غير المرغوب نضيف skip

read_csv("The first line of metadata
      The second line of metadata
      x,y,z
      1,2,3", skip = 2)
## # A tibble: 1 x 3
##       x     y     z
##   <dbl> <dbl> <dbl>
## 1     1     2     3

او اذا كان الملف يحتوي علي سطر يبداء مثلا بعلامه مثل الهاشتاق نضيف commentثم نحدد نوع العلامه

read_csv("# A comment I want to skip
      x,y,z
      1,2,3", comment = "#")
## # A tibble: 1 x 3
##       x     y     z
##   <dbl> <dbl> <dbl>
## 1     1     2     3

احيانا قد لايحتوي الملف على اسماء للاعمده(المتغيرات) في هذه الحاله نحتاج لاضافة الاسماء يديويا باستخدام colnames

read_csv("1,2,3
         4,5,6", col_names = c("x", "y", "z"))
## # A tibble: 2 x 3
##       x     y     z
##   <dbl> <dbl> <dbl>
## 1     1     2     3
## 2     4     5     6

بعض البيانات تستخدم . او_ للتعبير عن القيم المفقوده (Missing value)

هذه القيم لن تظهر كقيم مفقوده اذا تم قرائتها بالشكل الحالي لذالك سوف نحولها الي NA

read_csv("a,b,c
         1,2,.", na = ".")
## # A tibble: 1 x 3
##       a     b c    
##   <dbl> <dbl> <lgl>
## 1     1     2 NA

استخدام ()*_parse

ربما ايضا تواجة ايضا مشكلة ان العمود الذي يمثل المبالغ يحتوي علامة على “$” او انه يستعمل نقطه بدل الفاصله لتقسيم الارقام الكبيره

مثلا

1- $5,000,000

2- $5.000.000

3- 5000000

parse_number("$100")
## [1] 100
parse_number("20%")
## [1] 20
parse_number("It cost $123.45")
## [1] 123.45
# Used in America
parse_number("$123,456,789")
## [1] 123456789
# Used in many parts of Europe
parse_number("123.456.789", locale = locale(grouping_mark = "."))
## [1] 123456789
# Used in Switzerland
parse_number("123'456'789", locale = locale(grouping_mark = "'"))
## [1] 123456789

او اذا كانت القيمه التي تريدها اتحتوي على كسر

parse_double("1.23")
## [1] 1.23
parse_double("1,23", locale = locale(decimal_mark = ","))
## [1] 1.23

هناك ايضا

1- ()parse_date

2- ()parse_factor

3- ()parse_datetime

4- ()parse_logical

5- ()parse_vectr

6- ()parsee_character

7- ()parsee_time

8-()parsee_guess

بعض المشاكل مع البيانات الكبيره

()read_csv تقوم بقراءة اول 1000 صف ثم من اجل اختيار type العمود تقوم بتطبيق الشروط التالية عليه

  • logical : اذا احتوى على “T”, “F” , “TRUE” or “FALSE”.

  • integer: اذا احتوى على ارقام و علامة “-”.

  • double: اذا احتوى على كسور مثل “1.1”.

  • number: اذا احتوى على double مع علامة ال grouping mark.

  • time: يطابق ال default time_format.

  • date: يطابق ال default date_format.

  • date-time: اي قيمه من قيم ال ISO8601 date

تخيل الان لو ان لديك جدول يحتوي على عشرة الاف مشاهده. وان اول 1000 مشاهدة من العمود y الذي يمثل التاريخ مفقودة

كيف سيقراء R هذا الجدول

الجدول challenge يحتوي على هذة المشكلة

الان لنقم بقراءة الجدول

challenge <- read_csv(readr_example("challenge.csv"))
## Parsed with column specification:
## cols(
##   x = col_double(),
##   y = col_logical()
## )
## Warning: 1000 parsing failures.
##  row col           expected     actual                                                                                         file
## 1001   y 1/0/T/F/TRUE/FALSE 2015-01-16 '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/readr/extdata/challenge.csv'
## 1002   y 1/0/T/F/TRUE/FALSE 2018-05-18 '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/readr/extdata/challenge.csv'
## 1003   y 1/0/T/F/TRUE/FALSE 2015-09-05 '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/readr/extdata/challenge.csv'
## 1004   y 1/0/T/F/TRUE/FALSE 2012-11-28 '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/readr/extdata/challenge.csv'
## 1005   y 1/0/T/F/TRUE/FALSE 2020-01-13 '/Library/Frameworks/R.framework/Versions/3.6/Resources/library/readr/extdata/challenge.csv'
## .... ... .................. .......... ............................................................................................
## See problems(...) for more details.

تجاهل ()readr_example

لاحظ هنا الرساله Warning: 1000 parsing failures.

حتي ناخذ تصور افضل عن الخطاء سوف نستخدم problems()

problems(challenge)
## # A tibble: 1,000 x 5
##      row col   expected       actual   file                                     
##    <int> <chr> <chr>          <chr>    <chr>                                    
##  1  1001 y     1/0/T/F/TRUE/… 2015-01… '/Library/Frameworks/R.framework/Version…
##  2  1002 y     1/0/T/F/TRUE/… 2018-05… '/Library/Frameworks/R.framework/Version…
##  3  1003 y     1/0/T/F/TRUE/… 2015-09… '/Library/Frameworks/R.framework/Version…
##  4  1004 y     1/0/T/F/TRUE/… 2012-11… '/Library/Frameworks/R.framework/Version…
##  5  1005 y     1/0/T/F/TRUE/… 2020-01… '/Library/Frameworks/R.framework/Version…
##  6  1006 y     1/0/T/F/TRUE/… 2016-04… '/Library/Frameworks/R.framework/Version…
##  7  1007 y     1/0/T/F/TRUE/… 2011-05… '/Library/Frameworks/R.framework/Version…
##  8  1008 y     1/0/T/F/TRUE/… 2020-07… '/Library/Frameworks/R.framework/Version…
##  9  1009 y     1/0/T/F/TRUE/… 2011-04… '/Library/Frameworks/R.framework/Version…
## 10  1010 y     1/0/T/F/TRUE/… 2010-05… '/Library/Frameworks/R.framework/Version…
## # … with 990 more rows

نلاحظ هنا الاخطاء موجوده في العمود y حيث ان القيمه المتوقعة كانت Logial لاكن القيمه الفعليه Date

الان ()read_csv استبعد التاريخ ووضع جميع القيم من 1 الى 2000 ك قيم مفقودة

والسبب هو ان كما ذكرنا ان اول 1000 صف يحتوي على Missing values

ابسط طريقه لعلاج المشكله هي بزياده عدد الصفوف التي يعتمدها ()read_csv لتحديد ال type

challenge2 <- read_csv(readr_example("challenge.csv"),
                       guess_max = 1001)
## Parsed with column specification:
## cols(
##   x = col_double(),
##   y = col_date(format = "")
## )

الان تم حل المشكلة

حفظ (كتابه) الملفات

لحفظ الملف السابق

write_csv(challenge,"challenge.csv")

.لاكن لاحظ انه عند قرائته مره اخرى سنقع في نفس المشكلة السابقه

challenge
## # A tibble: 2,000 x 2
##        x y    
##    <dbl> <lgl>
##  1   404 NA   
##  2  4172 NA   
##  3  3004 NA   
##  4   787 NA   
##  5    37 NA   
##  6  2332 NA   
##  7  2489 NA   
##  8  1449 NA   
##  9  3665 NA   
## 10  3863 NA   
## # … with 1,990 more rows
write_csv(challenge2, "challenge-2.csv")
read_csv("challenge-2.csv")
## Parsed with column specification:
## cols(
##   x = col_double(),
##   y = col_logical()
## )
## # A tibble: 2,000 x 2
##        x y    
##    <dbl> <lgl>
##  1   404 NA   
##  2  4172 NA   
##  3  3004 NA   
##  4   787 NA   
##  5    37 NA   
##  6  2332 NA   
##  7  2489 NA   
##  8  1449 NA   
##  9  3665 NA   
## 10  3863 NA   
## # … with 1,990 more rows

والسبب هو ملفات csv لا تحتفظ ب type العمود

لاكن يمكننا استخدام

write_rds(challenge2, "challenge.rds")
read_rds("challenge.rds")
## # A tibble: 2,000 x 2
##        x y         
##    <dbl> <date>    
##  1   404 NA        
##  2  4172 NA        
##  3  3004 NA        
##  4   787 NA        
##  5    37 NA        
##  6  2332 NA        
##  7  2489 NA        
##  8  1449 NA        
##  9  3665 NA        
## 10  3863 NA        
## # … with 1,990 more rows

rds هي صيغه خاصه لحفظ البيانات في R

انظرا ايضا

1- ()write_excel_csv لحفظ البيانات بصيغة اكسل

2- ()write_tsv,

مكتبات اخرى تساعد في قراءه الملفات

  • haven: يقراء ملفات SPSS, Stata, and SAS

  • readxl: يقراء ملفات اكسل ( .xls and .xlsx).

  • DBI: يقراء الجداول من قواعد البيانات

Tidy data

مدخل

الجداول التاليه كلها تحتي على نفس البيانات لاكن طريقة العرض تختلف من جدول لآخر

المتغيرات هنا هي country, year, cases and population

table1
## # A tibble: 6 x 4
##   country      year  cases population
##   <chr>       <int>  <int>      <int>
## 1 Afghanistan  1999    745   19987071
## 2 Afghanistan  2000   2666   20595360
## 3 Brazil       1999  37737  172006362
## 4 Brazil       2000  80488  174504898
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583
table2
## # A tibble: 12 x 4
##    country      year type            count
##    <chr>       <int> <chr>           <int>
##  1 Afghanistan  1999 cases             745
##  2 Afghanistan  1999 population   19987071
##  3 Afghanistan  2000 cases            2666
##  4 Afghanistan  2000 population   20595360
##  5 Brazil       1999 cases           37737
##  6 Brazil       1999 population  172006362
##  7 Brazil       2000 cases           80488
##  8 Brazil       2000 population  174504898
##  9 China        1999 cases          212258
## 10 China        1999 population 1272915272
## 11 China        2000 cases          213766
## 12 China        2000 population 1280428583
table3
## # A tibble: 6 x 3
##   country      year rate             
## * <chr>       <int> <chr>            
## 1 Afghanistan  1999 745/19987071     
## 2 Afghanistan  2000 2666/20595360    
## 3 Brazil       1999 37737/172006362  
## 4 Brazil       2000 80488/174504898  
## 5 China        1999 212258/1272915272
## 6 China        2000 213766/1280428583
# Spread across two tibbles
# مقسمة على اكثر من جدول
table4a  # cases
## # A tibble: 3 x 3
##   country     `1999` `2000`
## * <chr>        <int>  <int>
## 1 Afghanistan    745   2666
## 2 Brazil       37737  80488
## 3 China       212258 213766
table4b  # population
## # A tibble: 3 x 3
##   country         `1999`     `2000`
## * <chr>            <int>      <int>
## 1 Afghanistan   19987071   20595360
## 2 Brazil       172006362  174504898
## 3 China       1272915272 1280428583

فقط واحد من هذي الجداول هو الاصلح للاستخدام مع tidyverse ونطلق علية tidy dataset

شروط ال Tidy dataset هي كالتالي :

1- كل عمود يمثل متغير

2- كل صف يمثل مشاهدة

3- كل قيمه تكون في خليه

طبعا من الواضح ان table1 هو الوحيد الذي تنطبق علية الشروط.

الهدف من ال Tidy data هو انها تمكننا من استخدام Tidyverse بالطريقة الامثل

على سبيل المثال

# Compute rate per 10,000
# حساب معدل الاصابات لكل 10 الاف شخص

table1 %>% 
  mutate(rate = cases / population * 10000)
## # A tibble: 6 x 5
##   country      year  cases population  rate
##   <chr>       <int>  <int>      <int> <dbl>
## 1 Afghanistan  1999    745   19987071 0.373
## 2 Afghanistan  2000   2666   20595360 1.29 
## 3 Brazil       1999  37737  172006362 2.19 
## 4 Brazil       2000  80488  174504898 4.61 
## 5 China        1999 212258 1272915272 1.67 
## 6 China        2000 213766 1280428583 1.67
# Compute cases per year
# حساب عدد الاصابات لكل سنه

table1 %>% 
  count(year, wt = cases)
## # A tibble: 2 x 2
##    year      n
##   <int>  <int>
## 1  1999 250740
## 2  2000 296920
# Visualise changes over time
# تصوير التغير خلال السنوات
library(ggplot2)
ggplot(table1, aes(year, cases)) + 
  geom_line(aes(group = country), colour = "grey50") + 
  geom_point(aes(colour = country))

احيانا البيانات لاتكون في شكل ال Tidy data لذلك هناك مجموعة من ال , functions التي تساعدنا في تحويلها

Pivoting ( التحويل من والى Tidy data )

هناك نوعين من المشاكل الشائعة في جداول البيانات هما ان يكون هناك

1- متغير واحد مقسم على اكثر من عمود

2- اكثر من متغير في عمود واحد

Pivot longer

متغير واحد مقسم على اكثر من عمود

# Cases table
table4a
## # A tibble: 3 x 3
##   country     `1999` `2000`
## * <chr>        <int>  <int>
## 1 Afghanistan    745   2666
## 2 Brazil       37737  80488
## 3 China       212258 213766

1- لاحظ ان year بدل ان تكون في عمود واحد توزعت على عمودين

2- لاحظ ان cases لم يعد لها عمود

الان سوف نقوم بوضع عمود خاص لكل من year and cases

table4a %>% 
  pivot_longer(c(`1999`, `2000`), names_to = "year", values_to = "cases")
## # A tibble: 6 x 3
##   country     year   cases
##   <chr>       <chr>  <int>
## 1 Afghanistan 1999     745
## 2 Afghanistan 2000    2666
## 3 Brazil      1999   37737
## 4 Brazil      2000   80488
## 5 China       1999  212258
## 6 China       2000  213766

بامكانك اختيار اي اسم تريد بدل cases او year

استخدام ' حول 1999 و 2000 هو بسبب انها تبدا برقم وليس اسم. انت لست بحاجة اليها اذا كان العمود يبدا بحرف.

Pivot wider

اكثر من متغير في عمود واحد

table2
## # A tibble: 12 x 4
##    country      year type            count
##    <chr>       <int> <chr>           <int>
##  1 Afghanistan  1999 cases             745
##  2 Afghanistan  1999 population   19987071
##  3 Afghanistan  2000 cases            2666
##  4 Afghanistan  2000 population   20595360
##  5 Brazil       1999 cases           37737
##  6 Brazil       1999 population  172006362
##  7 Brazil       2000 cases           80488
##  8 Brazil       2000 population  174504898
##  9 China        1999 cases          212258
## 10 China        1999 population 1272915272
## 11 China        2000 cases          213766
## 12 China        2000 population 1280428583

لاحظ ان المتغيرين population و cases مدموجين في عمود واحد

لاحظ ايضا ان

1- العمود الذي يحتوي على اسماء المتغيرات اسمه type

2- العمود الذي يحتوي على القيم اسمه count

table2 %>%
    pivot_wider(names_from = type, values_from = count)
## # A tibble: 6 x 4
##   country      year  cases population
##   <chr>       <int>  <int>      <int>
## 1 Afghanistan  1999    745   19987071
## 2 Afghanistan  2000   2666   20595360
## 3 Brazil       1999  37737  172006362
## 4 Brazil       2000  80488  174504898
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583

Spreading and uniting

Spread

لاحظ الجدول التالي

table3
## # A tibble: 6 x 3
##   country      year rate             
## * <chr>       <int> <chr>            
## 1 Afghanistan  1999 745/19987071     
## 2 Afghanistan  2000 2666/20595360    
## 3 Brazil       1999 37737/172006362  
## 4 Brazil       2000 80488/174504898  
## 5 China        1999 212258/1272915272
## 6 China        2000 213766/1280428583

العمود rate يحتوي على المتغيرين population و cases ويفصل بينهم /

table3 %>% 
  separate(rate, into = c("cases", "population"), sep = "/")

يمكنك استخدام sep مع regular expression

احيانا قد تحتاج الى تحويل type العمود

table3 %>% 
  separate(rate, into = c("cases", "population"), convert = TRUE)
## # A tibble: 6 x 4
##   country      year  cases population
##   <chr>       <int>  <int>      <int>
## 1 Afghanistan  1999    745   19987071
## 2 Afghanistan  2000   2666   20595360
## 3 Brazil       1999  37737  172006362
## 4 Brazil       2000  80488  174504898
## 5 China        1999 212258 1272915272
## 6 China        2000 213766 1280428583

اذا كانت قيمة sep عدد صحيح فإن ()separate سوف تقسم العمود حسب العدد

table3 %>% 
  separate(year, into = c("century", "year"), sep = 2)
## # A tibble: 6 x 4
##   country     century year  rate             
##   <chr>       <chr>   <chr> <chr>            
## 1 Afghanistan 19      99    745/19987071     
## 2 Afghanistan 20      00    2666/20595360    
## 3 Brazil      19      99    37737/172006362  
## 4 Brazil      20      00    80488/174504898  
## 5 China       19      99    212258/1272915272
## 6 China       20      00    213766/1280428583

Unite

تقوم بعملية عكسية لما تقوم به ()separate

table5 %>% 
  unite(new, century, year)
## # A tibble: 6 x 3
##   country     new   rate             
##   <chr>       <chr> <chr>            
## 1 Afghanistan 19_99 745/19987071     
## 2 Afghanistan 20_00 2666/20595360    
## 3 Brazil      19_99 37737/172006362  
## 4 Brazil      20_00 80488/174504898  
## 5 China       19_99 212258/1272915272
## 6 China       20_00 213766/1280428583

او

table5 %>% 
  unite(new, century, year, sep = "")
## # A tibble: 6 x 3
##   country     new   rate             
##   <chr>       <chr> <chr>            
## 1 Afghanistan 1999  745/19987071     
## 2 Afghanistan 2000  2666/20595360    
## 3 Brazil      1999  37737/172006362  
## 4 Brazil      2000  80488/174504898  
## 5 China       1999  212258/1272915272
## 6 China       2000  213766/1280428583

قيمه ال default هي _

Missing Values

هناك نوعين من القيم المفقوده

1- Explicitly : تحمل القيمه NA وتكون موجوده في البيانات

2- Implicitly: لاتكون موجوده في البيانات

.شاهد هذه الجول لتتتضح الصوره افضل

stocks <- tibble(
  year   = c(2015, 2015, 2015, 2015, 2016, 2016, 2016),
  qtr    = c(   1,    2,    3,    4,    2,    3,    4),
  return = c(1.88, 0.59, 0.35,   NA, 0.92, 0.17, 2.66)
)

1- ال return عند year == 15و qtr == 4 قيمته هي NA اذا هي Explicitly missing

2- ال return عند year == 16و qtr == 1 قيمته غير موجودة اذا هي Implicitly missing

stocks
## # A tibble: 7 x 3
##    year   qtr return
##   <dbl> <dbl>  <dbl>
## 1  2015     1   1.88
## 2  2015     2   0.59
## 3  2015     3   0.35
## 4  2015     4  NA   
## 5  2016     2   0.92
## 6  2016     3   0.17
## 7  2016     4   2.66

للتحويل من Implicitly missing الي Explicitly missing

ملاحظه: التحويل هنا يكون مفيدا غالبا مع time series analysis

stocks %>% 
  complete(year, qtr)
## # A tibble: 8 x 3
##    year   qtr return
##   <dbl> <dbl>  <dbl>
## 1  2015     1   1.88
## 2  2015     2   0.59
## 3  2015     3   0.35
## 4  2015     4  NA   
## 5  2016     1  NA   
## 6  2016     2   0.92
## 7  2016     3   0.17
## 8  2016     4   2.66

والعكس يكون

stocks %>% na.omit()
## # A tibble: 6 x 3
##    year   qtr return
##   <dbl> <dbl>  <dbl>
## 1  2015     1   1.88
## 2  2015     2   0.59
## 3  2015     3   0.35
## 4  2016     2   0.92
## 5  2016     3   0.17
## 6  2016     4   2.66

مثال اخر

treatment <- tribble(
  ~ person,           ~ treatment, ~response,
  "Derrick Whitmore", 1,           7,
  NA,                 2,           10,
  NA,                 3,           9,
  "Katherine Burke",  1,           4
)

يمكنك تغطية القيم المفقوده بقيمه الصف السابق او اللاحق

treatment %>% 
  fill(person)
## # A tibble: 4 x 3
##   person           treatment response
##   <chr>                <dbl>    <dbl>
## 1 Derrick Whitmore         1        7
## 2 Derrick Whitmore         2       10
## 3 Derrick Whitmore         3        9
## 4 Katherine Burke          1        4
treatment %>% 
  fill(person, .direction = "up")
## # A tibble: 4 x 3
##   person           treatment response
##   <chr>                <dbl>    <dbl>
## 1 Derrick Whitmore         1        7
## 2 Katherine Burke          2       10
## 3 Katherine Burke          3        9
## 4 Katherine Burke          1        4

Exercise

الجدول who ليس Tidy حاول تحويله الى Tidy

who
## # A tibble: 7,240 x 60
##    country iso2  iso3   year new_sp_m014 new_sp_m1524 new_sp_m2534 new_sp_m3544
##    <chr>   <chr> <chr> <int>       <int>        <int>        <int>        <int>
##  1 Afghan… AF    AFG    1980          NA           NA           NA           NA
##  2 Afghan… AF    AFG    1981          NA           NA           NA           NA
##  3 Afghan… AF    AFG    1982          NA           NA           NA           NA
##  4 Afghan… AF    AFG    1983          NA           NA           NA           NA
##  5 Afghan… AF    AFG    1984          NA           NA           NA           NA
##  6 Afghan… AF    AFG    1985          NA           NA           NA           NA
##  7 Afghan… AF    AFG    1986          NA           NA           NA           NA
##  8 Afghan… AF    AFG    1987          NA           NA           NA           NA
##  9 Afghan… AF    AFG    1988          NA           NA           NA           NA
## 10 Afghan… AF    AFG    1989          NA           NA           NA           NA
## # … with 7,230 more rows, and 52 more variables: new_sp_m4554 <int>,
## #   new_sp_m5564 <int>, new_sp_m65 <int>, new_sp_f014 <int>,
## #   new_sp_f1524 <int>, new_sp_f2534 <int>, new_sp_f3544 <int>,
## #   new_sp_f4554 <int>, new_sp_f5564 <int>, new_sp_f65 <int>,
## #   new_sn_m014 <int>, new_sn_m1524 <int>, new_sn_m2534 <int>,
## #   new_sn_m3544 <int>, new_sn_m4554 <int>, new_sn_m5564 <int>,
## #   new_sn_m65 <int>, new_sn_f014 <int>, new_sn_f1524 <int>,
## #   new_sn_f2534 <int>, new_sn_f3544 <int>, new_sn_f4554 <int>,
## #   new_sn_f5564 <int>, new_sn_f65 <int>, new_ep_m014 <int>,
## #   new_ep_m1524 <int>, new_ep_m2534 <int>, new_ep_m3544 <int>,
## #   new_ep_m4554 <int>, new_ep_m5564 <int>, new_ep_m65 <int>,
## #   new_ep_f014 <int>, new_ep_f1524 <int>, new_ep_f2534 <int>,
## #   new_ep_f3544 <int>, new_ep_f4554 <int>, new_ep_f5564 <int>,
## #   new_ep_f65 <int>, newrel_m014 <int>, newrel_m1524 <int>,
## #   newrel_m2534 <int>, newrel_m3544 <int>, newrel_m4554 <int>,
## #   newrel_m5564 <int>, newrel_m65 <int>, newrel_f014 <int>,
## #   newrel_f1524 <int>, newrel_f2534 <int>, newrel_f3544 <int>,
## #   newrel_f4554 <int>, newrel_f5564 <int>, newrel_f65 <int>

شرح لبعض الرموز

1- Country

2- اختصار لاسم الدولة iso2 and iso

3- year

4- من العمودالرابع نلاحظ المتغيرات غير مفهومة وشرحها هو كالتالي

  1. اول ثلاث احرف ترمز الى ان الحاله old او new

  2. الجزء بين “ـ” او الحرف الرابع يرمز الى

    • rel stands for cases of relapse
    • ep stands for cases of extrapulmonary TB
    • sn stands for cases of pulmonary TB that could not be diagnosed by a pulmonary smear (smear negative)
    • sp stands for cases of pulmonary TB that could be diagnosed be a pulmonary smear (smear positive)
  3. الحرف السادس يرمز الى الجنس “male” and “female”

  4. الجزء الباقي يرمز الى العمر

    • 014 = 0 – 14 years old
    • 1524 = 15 – 24 years old
    • 2534 = 25 – 34 years old
    • 3544 = 35 – 44 years old
    • 4554 = 45 – 54 years old
    • 5564 = 55 – 64 years old
    • 65 = 65 or older

شاهد case study 12.6

في الكتاب

Relationa Data

ال relational data تاتي في غالب الاحوال من قواعد البيانات (RDBMS)

وهي البيانات التكون مقسمة على اكثر من جدول مثلا ان يكون لديك جدول للرواتب وجدول لمعلومات الموظف الشخصية

.هناك ثلاث طرق لاضافة اكثر من جدول الى بعض

1- Mutating joins: اضافه اعمده جديده من جدول A تتطابق احد اعمدتها مع احد اعمدة جدول B

2- Filtering joins : ازاله بعض المشاهدات من الجدول A التي تطابق البيانات في احد الاعمدة من الجدولB

3- Set operations: مثل عمليات المجموعات في الرياضيات (تقاطع، اتحاد)

للتوضيح اكثر سوف نعمل على عده جداول تخص شركات الطيران من مكتبة nycflights13

library(nycflights13)

الجداول هي:

  • airlines

تعطينا اسم شركه الطيران مع الرمز الثنائي للشركة.

```r
airlines
```

```
## # A tibble: 16 x 2
##    carrier name                       
##    <chr>   <chr>                      
##  1 9E      Endeavor Air Inc.          
##  2 AA      American Airlines Inc.     
##  3 AS      Alaska Airlines Inc.       
##  4 B6      JetBlue Airways            
##  5 DL      Delta Air Lines Inc.       
##  6 EV      ExpressJet Airlines Inc.   
##  7 F9      Frontier Airlines Inc.     
##  8 FL      AirTran Airways Corporation
##  9 HA      Hawaiian Airlines Inc.     
## 10 MQ      Envoy Air                  
## 11 OO      SkyWest Airlines Inc.      
## 12 UA      United Air Lines Inc.      
## 13 US      US Airways Inc.            
## 14 VX      Virgin America             
## 15 WN      Southwest Airlines Co.     
## 16 YV      Mesa Airlines Inc.
```
  • airports

تعطينا معلومات المطار. نستطيع ان نميز كل مطار عن طريق العمود faa اي رمز المطار .

```r
airports
```

```
## # A tibble: 1,458 x 8
##    faa   name                       lat    lon   alt    tz dst   tzone          
##    <chr> <chr>                    <dbl>  <dbl> <dbl> <dbl> <chr> <chr>          
##  1 04G   Lansdowne Airport         41.1  -80.6  1044    -5 A     America/New_Yo…
##  2 06A   Moton Field Municipal A…  32.5  -85.7   264    -6 A     America/Chicago
##  3 06C   Schaumburg Regional       42.0  -88.1   801    -6 A     America/Chicago
##  4 06N   Randall Airport           41.4  -74.4   523    -5 A     America/New_Yo…
##  5 09J   Jekyll Island Airport     31.1  -81.4    11    -5 A     America/New_Yo…
##  6 0A9   Elizabethton Municipal …  36.4  -82.2  1593    -5 A     America/New_Yo…
##  7 0G6   Williams County Airport   41.5  -84.5   730    -5 A     America/New_Yo…
##  8 0G7   Finger Lakes Regional A…  42.9  -76.8   492    -5 A     America/New_Yo…
##  9 0P2   Shoestring Aviation Air…  39.8  -76.6  1000    -5 U     America/New_Yo…
## 10 0S9   Jefferson County Intl     48.1 -123.    108    -8 A     America/Los_An…
## # … with 1,448 more rows
```
  • planes

يعطينا معلومات كل طائرة، نستطيع تمييز كل طائره باستخدام العمود tailnum .

```r
planes
```

```
## # A tibble: 3,322 x 9
##    tailnum  year type          manufacturer   model  engines seats speed engine 
##    <chr>   <int> <chr>         <chr>          <chr>    <int> <int> <int> <chr>  
##  1 N10156   2004 Fixed wing m… EMBRAER        EMB-1…       2    55    NA Turbo-…
##  2 N102UW   1998 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
##  3 N103US   1999 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
##  4 N104UW   1999 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
##  5 N10575   2002 Fixed wing m… EMBRAER        EMB-1…       2    55    NA Turbo-…
##  6 N105UW   1999 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
##  7 N107US   1999 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
##  8 N108UW   1999 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
##  9 N109UW   1999 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
## 10 N110UW   1999 Fixed wing m… AIRBUS INDUST… A320-…       2   182    NA Turbo-…
## # … with 3,312 more rows
```
  • weather

يعطينا معلومات الطقس في مطارات NYC لكل ساعة .

```r
weather
```

```
## # A tibble: 26,115 x 15
##    origin  year month   day  hour  temp  dewp humid wind_dir wind_speed
##    <chr>  <int> <int> <int> <int> <dbl> <dbl> <dbl>    <dbl>      <dbl>
##  1 EWR     2013     1     1     1  39.0  26.1  59.4      270      10.4 
##  2 EWR     2013     1     1     2  39.0  27.0  61.6      250       8.06
##  3 EWR     2013     1     1     3  39.0  28.0  64.4      240      11.5 
##  4 EWR     2013     1     1     4  39.9  28.0  62.2      250      12.7 
##  5 EWR     2013     1     1     5  39.0  28.0  64.4      260      12.7 
##  6 EWR     2013     1     1     6  37.9  28.0  67.2      240      11.5 
##  7 EWR     2013     1     1     7  39.0  28.0  64.4      240      15.0 
##  8 EWR     2013     1     1     8  39.9  28.0  62.2      250      10.4 
##  9 EWR     2013     1     1     9  39.9  28.0  62.2      260      15.0 
## 10 EWR     2013     1     1    10  41    28.0  59.6      260      13.8 
## # … with 26,105 more rows, and 5 more variables: wind_gust <dbl>, precip <dbl>,
## #   pressure <dbl>, visib <dbl>, time_hour <dttm>
```

ال Diagram التالي يشرح العلاقات بين جميع الجداول السابقة

الهدف من ال Diagram هو ان نعرف كيف نربط الجداول السابقة مع بعض .

مثلا

  • flights يرتبط ب planes عن طريق العمود tailnum .

  • flights يرتبط ب airlines عن طريق العمود carrier .

  • flights يرتبط ب airports بطريقتين الاولى عن طريق origin وذالك اذا اردنا الحصول عل معلومات مطار الاقلاع والثانيه عن طريق dest وذالك اذا اردنا الحصول على معلومات مطار الوصول .

  • flights يرتبط ب weather عن طريق الاعمده التي تثمل الوقت ( year, month, day and hour ) وعمود الموقع origin

Keys

  • primary key : يميز كل مشاهدة في جدولها

    مثال : planes$tailnum هي primary key للجدول plans لان كل طائره لها مشاهدة واحدة فقط

  • foreign key : يميز كل مشاهدة في جدول آخر

مثال : flights$tailnum هو foreign key لانه موجود في جدول flights لاكن يمكن ان يتكرر (لان الطائره ممكن تعمل اكثر من رحلة) لاكنة primaray key لاكن من خلالة يمكننا الربط مع جدول planes

الان لنتاكد ان ان الشروط تنطبق هنا

#tailnum هنا نختبر اذا كان لدينا اكثر من قيمه في العمود 
# planes في الجدول  primary key حيث انه هو ال

planes %>% 
  count(tailnum) %>% 
  filter(n > 1)
## # A tibble: 0 x 2
## # … with 2 variables: tailnum <chr>, n <int>
weather %>% 
  count(year, month, day, hour, origin) %>% 
  filter(n > 1)
## # A tibble: 3 x 6
##    year month   day  hour origin     n
##   <int> <int> <int> <int> <chr>  <int>
## 1  2013    11     3     1 EWR        2
## 2  2013    11     3     1 JFK        2
## 3  2013    11     3     1 LGA        2

لاحظ ان الاعمده التي يجب ان تكون primary key في الجدول weather، لم تفي بالشروط لذالك لايمكن اعتبارها primary key .

احيانا قد يكون كل صف بالفعل يمثل مشاهدة لاكن لانستطيع ايجاد التوليفة المناسبه من الاعمدة لتشكيل primary key

في هذه الحاله ربما تحتاج الى البحث عن عمود يساعد في جعل كل مشاهده مميزه او يمكنك اضافه row_number() ويسمى هذا ال key surrogate key

اضافة

مصممو قواعد البيانات لايحبون تكرار البيانات لذالك يقومون بعملية تسمى .Decomposition

.الهدف من هذه العملية هي ازاله البيانات المتكرره ووضعها في جدول اخر

مثال

كل شركة تزود موضفيها برقم وضيفي، الهدف منه هو تمييز كل موضف عن الاخر، بحيث اننا نستطيع معرفه .معلومات الموضف بمعرفه رقمة الوضيفي

الان لنفرض اننا نريد عمل قاعده بيانات توضح رواتب الموظفين. هل نضع جميع معلومات الموضفين في جدول .الرواتب او نكتفي فقط برقمهم الوظيفي

مصممين قواعد البيانات يرون انه من الافضل عمل جدولين. واحد لمعلومات الموضفين والاخر للرواتب

.بحيث يكون الرقم الوضيفي هو الرابط بين الجدولين

الان نطلق على الرقم الوضيفي لقب Primary key

لنفرض مثلا بان لدينا جدول اخر يمثل الحضور والغياب. لجميع الموضفين خلال السنه الفائته، يحتوي مثلا على رقم الموضف و التاريخ و الحاله

في هذه الحاله الرقم الوضيفي يفقد في هذا الجدول لقب Primary key

لاننا لانستطيع من خلالة تميز المشاهدات. ويكون ال Primary key هو تاريخ اليوم + الرقم الوضيفي. ويصبح الرقم الوضيفي foreign key

لاحظ انه الان الرقم الوضيفي اصبح Primary key في جدول العلومات الشخصية و جدول الرواتب

و foreign key
في جدول الحضور

واصبح الرقم الوضيفي مع التاريخ هو Primary key في جدول الحضور

Mutating joins

وهي عمليه عمليه شبية ب mutate() .حيث نقوم بإضافة اعمده اضافيه

على سبيل المثال flights2 خذ الجدول

flights2 <- flights %>% 
  select(year:day, hour, origin, dest, tailnum, carrier)
flights2
## # A tibble: 336,776 x 8
##     year month   day  hour origin dest  tailnum carrier
##    <int> <int> <int> <dbl> <chr>  <chr> <chr>   <chr>  
##  1  2013     1     1     5 EWR    IAH   N14228  UA     
##  2  2013     1     1     5 LGA    IAH   N24211  UA     
##  3  2013     1     1     5 JFK    MIA   N619AA  AA     
##  4  2013     1     1     5 JFK    BQN   N804JB  B6     
##  5  2013     1     1     6 LGA    ATL   N668DN  DL     
##  6  2013     1     1     5 EWR    ORD   N39463  UA     
##  7  2013     1     1     6 EWR    FLL   N516JB  B6     
##  8  2013     1     1     6 LGA    IAD   N829AS  EV     
##  9  2013     1     1     6 JFK    MCO   N593JB  B6     
## 10  2013     1     1     6 LGA    ORD   N3ALAA  AA     
## # … with 336,766 more rows

الان سوف نقوم باضافة اسماء شركات الطيران من جدول airlines

flights2 %>%
  select(-origin, -dest) %>% 
  left_join(airlines, by = "carrier")
## # A tibble: 336,776 x 7
##     year month   day  hour tailnum carrier name                    
##    <int> <int> <int> <dbl> <chr>   <chr>   <chr>                   
##  1  2013     1     1     5 N14228  UA      United Air Lines Inc.   
##  2  2013     1     1     5 N24211  UA      United Air Lines Inc.   
##  3  2013     1     1     5 N619AA  AA      American Airlines Inc.  
##  4  2013     1     1     5 N804JB  B6      JetBlue Airways         
##  5  2013     1     1     6 N668DN  DL      Delta Air Lines Inc.    
##  6  2013     1     1     5 N39463  UA      United Air Lines Inc.   
##  7  2013     1     1     6 N516JB  B6      JetBlue Airways         
##  8  2013     1     1     6 N829AS  EV      ExpressJet Airlines Inc.
##  9  2013     1     1     6 N593JB  B6      JetBlue Airways         
## 10  2013     1     1     6 N3ALAA  AA      American Airlines Inc.  
## # … with 336,766 more rows

كيف يعمل *()_join

x <- tribble(
  ~key, ~val_x,
     1, "x1",
     2, "x2",
     3, "x3"
)
y <- tribble(
  ~key, ~val_y,
     1, "y1",
     2, "y2",
     4, "y3"
)

inner join الربط الداخلي

في الربط الداخلي نبقي فقط المشاهدات المتشابهة الموجوده في العمود key

في كل من الجدول x and y

x %>% 
  inner_join(y, by = "key")
## # A tibble: 2 x 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1 x1    y1   
## 2     2 x2    y2

الربط الخارجي outer join

في الربط الخارجي نبقي كل المشاهدات الموجودة في الجدول x

مع مايتقاطع معها من الجدول
y

left join

x %>% 
  left_join(y, by = "key")
## # A tibble: 3 x 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1 x1    y1   
## 2     2 x2    y2   
## 3     3 x3    <NA>

right join

x %>% 
  right_join(y, by = "key")
## # A tibble: 3 x 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1 x1    y1   
## 2     2 x2    y2   
## 3     4 <NA>  y3

full join

x %>% 
  full_join(y, by = "key")
## # A tibble: 4 x 3
##     key val_x val_y
##   <dbl> <chr> <chr>
## 1     1 x1    y1   
## 2     2 x2    y2   
## 3     3 x3    <NA> 
## 4     4 <NA>  y3

filter join

Semi join

يبقي فقط المشاهدات الموجودة في x التي تتطابق مع
y لاكن بدون تضمين قيم y

x %>% 
  semi_join(y, by = "key")
## # A tibble: 2 x 2
##     key val_x
##   <dbl> <chr>
## 1     1 x1   
## 2     2 x2

anti join

x %>% 
  anti_join(y, by = "key")
## # A tibble: 1 x 2
##     key val_x
##   <dbl> <chr>
## 1     3 x3

يبقي المشاهدة الموجودة في x لاكن غير موجودة في y