17 Tarih ve saatler
17.1 Giriş
Bu bölüm R’da tarih ve saatlerle nasıl çalışacağınızı gösterecek. İlk bakışta tarih ve saatler basit görünür. Günlük yaşamınızda onları sürekli kullanırsınız ve pek kafa karışıklığına yol açmıyor gibidirler. Ancak tarih ve saatler hakkında daha fazla şey öğrendikçe giderek karmaşıklaştıklarını görürsünüz!
Başlangıç olarak bir yılda kaç gün, bir günde kaç saat olduğunu düşünün. Muhtemelen çoğu yılın 365, artık yılların ise 366 gün olduğunu hatırladınız. Bir yılın artık yıl olup olmadığını belirleyen kuralın tamamını biliyor musunuz1? Bir gündeki saat sayısı biraz daha belirsizdir: Çoğu gün 24 saattir ancak yaz saati uygulamasını kullanan yerlerde her yıl bir gün 23, başka bir gün ise 25 saattir.
Tarih ve saatler zordur; çünkü iki fiziksel olguyu (Dünya’nın kendi ekseni etrafındaki dönüşü ve Güneş çevresindeki yörüngesi) aylar, saat dilimleri ve yaz saati uygulaması dahil bir dizi jeopolitik olguyla uzlaştırmak zorundadır. Bu bölüm tarih ve saatlerle ilgili son ayrıntıya kadar her şeyi öğretmeyecek ancak yaygın veri analizi sorunlarında işinize yarayacak uygulamalı beceriler için sağlam bir temel sunacaktır.
Çeşitli girdilerden tarih-saat oluşturmayı ve ardından yıl, ay ve gün gibi bileşenleri çıkarmayı göstererek başlayacağız. Sonra yapmak istediğiniz işleme göre farklı türleri bulunan zaman aralıklarıyla çalışmanın zorlu ayrıntılarına gireceğiz. Bölümü saat dilimlerinin doğurduğu ek güçlükleri kısaca ele alarak bitireceğiz.
17.1.1 Ön koşullar
Bu bölüm R’da tarih ve saatlerle çalışmayı kolaylaştıran lubridate paketine odaklanacak. lubridate, tidyverse’in güncel sürümü itibarıyla temel tidyverse’in bir parçasıdır. Alıştırma verileri için nycflights13 paketine de ihtiyacımız olacak.
17.2 Tarih/saat oluşturma
Zamandaki bir ana başvuran üç tarih/saat verisi türü vardır:
Bir tarih. Tibbles bunu
<date>olarak yazdırır.Bir gün içindeki saat. Tibbles bunu
<time>olarak yazdırır.Tarih-saat, tarih ile saatin birleşimidir: Zamandaki bir anı benzersiz biçimde (genellikle en yakın saniyeye kadar) tanımlar. Tibbles bunu
<dttm>olarak yazdırır. Temel R bunlara POSIXct der ama bu adın pek akılda kalıcı olduğu söylenemez.
R’ın saatleri saklamak için yerleşik bir sınıfı olmadığından bu bölümde tarihlere ve tarih-saatlere odaklanacağız. Böyle bir sınıfa ihtiyacınız varsa hms paketini kullanabilirsiniz.
Her zaman ihtiyacınızı karşılayan en basit veri türünü kullanmalısınız. Bu, tarih-saat yerine tarih kullanabiliyorsanız tarihi tercih etmeniz gerektiği anlamına gelir. Saat dilimlerini ele alma zorunluluğu nedeniyle tarih-saatler çok daha karmaşıktır; bölümün sonunda bu konuya döneceğiz.
Geçerli tarih veya tarih-saati almak için today() ya da now() kullanabilirsiniz:
Aşağıdaki bölümlerde tarih/saat oluşturmak için kullanacağınız dört yöntem açıklanmaktadır:
- readr ile dosya okurken.
- Bir karakter dizisinden.
- Ayrı tarih-saat bileşenlerinden.
- Mevcut bir tarih/saat nesnesinden.
17.2.1 İçe aktarma sırasında
CSV dosyanız ISO8601 tarih veya tarih-saat içeriyorsa hiçbir şey yapmanız gerekmez; readr bunu otomatik olarak tanır:
csv <- "
date,datetime
2022-01-02,2022-01-02 05:12
"
read_csv(csv)
#> Warning: The `file` argument of `read_csv()` should use `I()` for literal data as of
#> readr 2.2.0.
#>
#> # Bad (for example):
#> read_csv("x,y\n1,2")
#>
#> # Good:
#> read_csv(I("x,y\n1,2"))
#> # A tibble: 1 × 2
#> date datetime
#> <date> <dttm>
#> 1 2022-01-02 2022-01-02 05:12:00ISO8601 standardını daha önce duymadıysanız bu, tarih bileşenlerinin büyükten küçüğe sıralanıp - ile ayrıldığı uluslararası bir tarih yazım standardıdır2. Örneğin 3 Mayıs 2022, ISO8601’de 2022-05-03 olarak yazılır. ISO8601 tarihleri saat de içerebilir; saat, dakika ve saniye : ile, tarih ve saat bileşenleri ise T ya da boşlukla ayrılır. Örneğin 3 Mayıs 2022 saat 16.26’yı 2022-05-03 16:26 veya 2022-05-03T16:26 olarak yazabilirsiniz.
Diğer tarih-saat biçimlerinde col_types ile birlikte col_date() veya col_datetime() ve bir tarih-saat biçimi kullanmanız gerekir. readr’ın kullandığı tarih-saat biçimi birçok programlama dilinde kullanılan bir standarttır ve tarih bileşenini % ile onu izleyen tek bir karakterle tanımlar. Örneğin %Y-%m-%d; yıl, -, sayı olarak ay, - ve günden oluşan bir tarihi belirtir. Tablo 17.1 tüm seçenekleri listeler.
| Tür | Kod | Anlam | Örnek |
|---|---|---|---|
| Yıl | %Y |
4 basamaklı yıl | 2021 |
%y |
2 basamaklı yıl | 21 | |
| Ay | %m |
Sayı | 2 |
%b |
Kısaltılmış ad | Feb | |
%B |
Tam ad | February | |
| Gün | %d |
Bir veya iki basamak | 2 |
%e |
İki basamak | 02 | |
| Saat | %H |
24 saatlik düzende saat | 13 |
%I |
12 saatlik düzende saat | 1 | |
%p |
AM/PM | pm | |
%M |
Dakika | 35 | |
%S |
Saniye | 45 | |
%OS |
Ondalık bileşenli saniye | 45.35 | |
%Z |
Saat dilimi adı | America/Chicago | |
%z |
UTC’den fark | +0800 | |
| Diğer | %. |
Rakam olmayan bir öğeyi atla | : |
%* |
Rakam olmayan tüm öğeleri atla |
Bu kod ise oldukça belirsiz bir tarihe uygulanan birkaç seçeneği gösterir:
csv <- "
date
01/02/15
"
read_csv(csv, col_types = cols(date = col_date("%m/%d/%y")))
#> # A tibble: 1 × 1
#> date
#> <date>
#> 1 2015-01-02
read_csv(csv, col_types = cols(date = col_date("%d/%m/%y")))
#> # A tibble: 1 × 1
#> date
#> <date>
#> 1 2015-02-01
read_csv(csv, col_types = cols(date = col_date("%y/%m/%d")))
#> # A tibble: 1 × 1
#> date
#> <date>
#> 1 2001-02-15Tarih biçimini nasıl belirtirseniz belirtin, tarih R’a içe aktarıldıktan sonra her zaman aynı biçimde görüntülenir.
%b veya %B kullanıyor ve İngilizce dışındaki tarihlerle çalışıyorsanız bir locale() da sağlamanız gerekir. date_names_langs() içindeki yerleşik diller listesine bakın ya da date_names() ile kendinizinkini oluşturun.
17.2.2 Karakter dizilerinden
Tarih-saat belirtim dili güçlüdür ancak tarih biçiminin dikkatle incelenmesini gerektirir. Alternatif bir yaklaşım, bileşenlerin sırasını belirttiğinizde biçimi otomatik olarak saptamaya çalışan lubridate yardımcılarını kullanmaktır. Bunları kullanmak için tarihlerinizde yıl, ay ve günün hangi sırada yer aldığını belirleyip “y”, “m” ve “d” harflerini aynı sıraya koyun. Bu size tarihinizi ayrıştıracak lubridate fonksiyonunun adını verir. Örneğin:
ymd() ve benzeri fonksiyonlar tarih oluşturur. Tarih-saat oluşturmak için ayrıştırma fonksiyonunun adına alt çizgi ve “h”, “m”, “s” harflerinden birini ya da birkaçını ekleyin:
Bir saat dilimi sağlayarak tarihten tarih-saat oluşturulmasını da zorunlu kılabilirsiniz:
ymd("2017-01-31", tz = "UTC")
#> [1] "2017-01-31 UTC"Burada GMT ya da Greenwich Ortalama Saati olarak da bilebileceğiniz, 0° boylamındaki saat olan UTC3 saat dilimini kullanıyorum4. UTC yaz saati uygulamasını kullanmadığından onunla hesaplama yapmak biraz daha kolaydır.
17.2.3 Ayrı bileşenlerden
Bazen tek bir karakter dizisi yerine tarih-saatin ayrı bileşenleri birden çok sütuna dağılmış olur. flights verisinde durum böyledir:
flights |>
select(year, month, day, hour, minute)
#> # A tibble: 336,776 × 5
#> year month day hour minute
#> <int> <int> <int> <dbl> <dbl>
#> 1 2013 1 1 5 15
#> 2 2013 1 1 5 29
#> 3 2013 1 1 5 40
#> 4 2013 1 1 5 45
#> 5 2013 1 1 6 0
#> 6 2013 1 1 5 58
#> # ℹ 336,770 more rowsBu tür bir girdiden tarih/saat oluşturmak için tarihlerde make_date(), tarih-saatlerde make_datetime() kullanın:
flights |>
select(year, month, day, hour, minute) |>
mutate(departure = make_datetime(year, month, day, hour, minute))
#> # A tibble: 336,776 × 6
#> year month day hour minute departure
#> <int> <int> <int> <dbl> <dbl> <dttm>
#> 1 2013 1 1 5 15 2013-01-01 05:15:00
#> 2 2013 1 1 5 29 2013-01-01 05:29:00
#> 3 2013 1 1 5 40 2013-01-01 05:40:00
#> 4 2013 1 1 5 45 2013-01-01 05:45:00
#> 5 2013 1 1 6 0 2013-01-01 06:00:00
#> 6 2013 1 1 5 58 2013-01-01 05:58:00
#> # ℹ 336,770 more rowsAynı işlemi flights içindeki dört saat sütununun her biri için yapalım. Saatler biraz sıra dışı bir biçimde gösterildiğinden saat ve dakika bileşenlerini çıkarmak için modüler aritmetik kullanıyoruz. Tarih-saat değişkenlerini oluşturduktan sonra bölümün geri kalanında inceleyeceğimiz değişkenlere odaklanıyoruz.
make_datetime_100 <- function(year, month, day, time) {
make_datetime(year, month, day, time %/% 100, time %% 100)
}
flights_dt <- flights |>
filter(!is.na(dep_time), !is.na(arr_time)) |>
mutate(
dep_time = make_datetime_100(year, month, day, dep_time),
arr_time = make_datetime_100(year, month, day, arr_time),
sched_dep_time = make_datetime_100(year, month, day, sched_dep_time),
sched_arr_time = make_datetime_100(year, month, day, sched_arr_time)
) |>
select(origin, dest, ends_with("delay"), ends_with("time"))
flights_dt
#> # A tibble: 328,063 × 9
#> origin dest dep_delay arr_delay dep_time sched_dep_time
#> <chr> <chr> <dbl> <dbl> <dttm> <dttm>
#> 1 EWR IAH 2 11 2013-01-01 05:17:00 2013-01-01 05:15:00
#> 2 LGA IAH 4 20 2013-01-01 05:33:00 2013-01-01 05:29:00
#> 3 JFK MIA 2 33 2013-01-01 05:42:00 2013-01-01 05:40:00
#> 4 JFK BQN -1 -18 2013-01-01 05:44:00 2013-01-01 05:45:00
#> 5 LGA ATL -6 -25 2013-01-01 05:54:00 2013-01-01 06:00:00
#> 6 EWR ORD -4 12 2013-01-01 05:54:00 2013-01-01 05:58:00
#> # ℹ 328,057 more rows
#> # ℹ 3 more variables: arr_time <dttm>, sched_arr_time <dttm>, …Bu verilerle kalkış saatlerinin yıl içindeki dağılımını görselleştirebiliriz:
flights_dt |>
ggplot(aes(x = dep_time)) +
geom_freqpoly(binwidth = 86400) # 86400 saniye = 1 gün
Ya da tek bir gün içinde:
flights_dt |>
filter(dep_time < ymd(20130102)) |>
ggplot(aes(x = dep_time)) +
geom_freqpoly(binwidth = 600) # 600 saniye = 10 dakika
Tarih-saatleri sayısal bir bağlamda (örneğin histogramda) kullandığınızda 1’in 1 saniye anlamına geldiğine dikkat edin; dolayısıyla 86400’lük aralık genişliği bir gün demektir. Tarihler için 1, bir gün anlamına gelir.
17.2.4 Diğer türlerden
Tarih-saat ile tarih arasında geçiş yapmak isteyebilirsiniz. Bu, as_datetime() ve as_date() fonksiyonlarının görevidir:
as_datetime(today())
#> [1] "2026-08-23 UTC"
as_date(now())
#> [1] "2026-08-23"Bazen tarih/saatleri “Unix başlangıcı” olan 1970-01-01’den sayısal farklar biçiminde alırsınız. Fark saniye cinsindeyse as_datetime(), gün cinsindeyse as_date() kullanın.
as_datetime(60 * 60 * 10)
#> [1] "1970-01-01 10:00:00 UTC"
as_date(365 * 10 + 2)
#> [1] "1980-01-01"17.2.5 Alıştırmalar
-
Geçersiz tarihler içeren bir karakter dizisini ayrıştırırsanız ne olur?
today()fonksiyonununtzoneargümanı ne yapar? Neden önemlidir?-
Aşağıdaki tarih-saatlerin her birini readr sütun belirtimi ve lubridate fonksiyonuyla nasıl ayrıştıracağınızı gösterin.
d1 <- "January 1, 2010" d2 <- "2015-Mar-07" d3 <- "06-Jun-2017" d4 <- c("August 19 (2015)", "July 1 (2015)") d5 <- "12/30/14" # 30 Aralık 2014 t1 <- "1705" t2 <- "11:15:10.12 PM"
17.3 Tarih-saat bileşenleri
Tarih-saat verilerini R’ın tarih-saat veri yapılarına nasıl içe aktaracağınızı öğrendiğinize göre bunlarla neler yapabileceğinizi inceleyelim. Bu bölüm ayrı bileşenleri alıp ayarlamanızı sağlayan erişim fonksiyonlarına odaklanacak. Sonraki bölümde tarih-saatlerle aritmetiğin nasıl çalıştığına bakacağız.
17.3.1 Bileşenleri alma
Tarihin ayrı bölümlerini year(), month(), mday() (ayın günü), yday() (yılın günü), wday() (haftanın günü), hour(), minute() ve second() erişim fonksiyonlarıyla çıkarabilirsiniz. Bunlar temelde make_datetime() fonksiyonunun tersidir.
month() ve wday() fonksiyonlarında ayın veya haftanın gününün kısaltılmış adını döndürmek için label = TRUE ayarını kullanabilirsiniz. Tam adı döndürmek için abbr = FALSE ayarını kullanın.
Hafta içi hafta sonuna göre daha fazla uçuş kalktığını görmek için wday() kullanabiliriz:
Saat içindeki dakikaya göre ortalama kalkış gecikmesine de bakabiliriz. İlginç bir örüntü vardır: 20-30 ve 50-60. dakikalar arasında kalkan uçuşların gecikmeleri saatin geri kalanına göre çok daha düşüktür!

İlginç biçimde planlanan kalkış saatine baktığımızda bu kadar güçlü bir örüntü görmeyiz:

Öyleyse gerçek kalkış saatlerinde bu örüntüyü neden görüyoruz? İnsanlar tarafından toplanan birçok veride olduğu gibi Şekil 17.1 üzerinde görüldüğü üzere uçuşların “yuvarlak” saatlerde kalkmasına yönelik güçlü bir eğilim vardır. İnsan yargısı içeren verilerle çalışırken bu tür örüntülere karşı her zaman dikkatli olun!
17.3.2 Yuvarlama
Ayrı bileşenleri çizmenin alternatif bir yolu, floor_date(), round_date() ve ceiling_date() ile tarihi yakındaki bir zaman birimine yuvarlamaktır. Her fonksiyon, ayarlanacak tarih vektörünü ve ardından aşağı, yukarı veya en yakına yuvarlanacak birimin adını alır. Örneğin bu yöntem haftalık uçuş sayısını çizmemizi sağlar:
flights_dt |>
count(week = floor_date(dep_time, "week")) |>
ggplot(aes(x = week, y = n)) +
geom_line() +
geom_point()
dep_time ile günün en erken anı arasındaki farkı hesaplayarak uçuşların gün içindeki dağılımını göstermek için yuvarlamayı kullanabilirsiniz:
flights_dt |>
mutate(dep_hour = dep_time - floor_date(dep_time, "day")) |>
ggplot(aes(x = dep_hour)) +
geom_freqpoly(binwidth = 60 * 30)
#> Don't know how to automatically pick scale for object of type <difftime>.
#> Defaulting to continuous.
Bir tarih-saat çifti arasındaki farkı hesaplamak bir difftime üretir (Bölüm 17.4.3 bölümünde daha ayrıntılı ele alınacaktır). Daha yararlı bir x ekseni elde etmek için bunu bir hms nesnesine dönüştürebiliriz:
flights_dt |>
mutate(dep_hour = hms::as_hms(dep_time - floor_date(dep_time, "day"))) |>
ggplot(aes(x = dep_hour)) +
geom_freqpoly(binwidth = 60 * 30)
17.3.3 Bileşenleri değiştirme
Her erişim fonksiyonunu tarih/saat bileşenlerini değiştirmek için de kullanabilirsiniz. Bu, veri analizinde sık gerekmez ancak açıkça hatalı tarihler içeren verileri temizlerken yararlı olabilir.
Alternatif olarak mevcut bir değişkeni değiştirmek yerine update() ile yeni bir tarih-saat oluşturabilirsiniz. Bu fonksiyon birden çok değeri tek adımda ayarlamanızı da sağlar:
update(datetime, year = 2030, month = 2, mday = 2, hour = 2)
#> [1] "2030-02-02 02:34:56 UTC"Değerler fazla büyükse sonraki birime devreder:
17.3.4 Alıştırmalar
Bir gün içindeki uçuş saatlerinin dağılımı yıl boyunca nasıl değişir?
dep_time,sched_dep_timevedep_delaydeğişkenlerini karşılaştırın. Birbirleriyle tutarlı mı? Bulgularınızı açıklayın.air_timeile kalkış ve varış arasındaki süreyi karşılaştırın. Bulgularınızı açıklayın. (İpucu: Havaalanının konumunu göz önünde bulundurun.)Ortalama gecikme süresi gün boyunca nasıl değişir?
dep_timemı yoksasched_dep_timemı kullanmalısınız? Neden?Gecikme olasılığını en aza indirmek istiyorsanız haftanın hangi günü yola çıkmalısınız?
diamonds$caratileflights$sched_dep_timedağılımlarını benzer kılan nedir?20-30 ve 50-60. dakikalar arasındaki erken kalkışların, planlanandan erken kalkan uçuşlardan kaynaklandığı hipotezimizi doğrulayın. İpucu: Bir uçuşun gecikip gecikmediğini belirten ikili bir değişken oluşturun.
17.4 Zaman aralıkları
Sırada çıkarma, toplama ve bölme dahil tarihlerle aritmetiğin nasıl çalıştığını öğreneceksiniz. Bu sırada zaman aralıklarını temsil eden üç önemli sınıfı tanıyacaksınız:
- Kesin bir saniye sayısını temsil eden süreler (durations).
- Hafta ve ay gibi insani birimleri temsil eden dönemler (periods).
- Bir başlangıç ve bitiş noktasını temsil eden aralıklar (intervals).
Süre, dönem ve aralık arasında nasıl seçim yaparsınız? Her zamanki gibi probleminizi çözen en basit veri yapısını seçin. Yalnızca fiziksel zamanla ilgileniyorsanız süreyi; insani zaman birimleri eklemeniz gerekiyorsa dönemi; bir zaman aralığının insani birimlerle ne kadar uzun olduğunu bulmanız gerekiyorsa aralığı kullanın.
17.4.1 Süreler
R’da iki tarihi çıkardığınızda bir difftime nesnesi elde edersiniz:
difftime sınıfı nesnesi saniye, dakika, saat, gün veya hafta cinsinden bir zaman aralığını kaydeder. Bu belirsizlik difftime nesneleriyle çalışmayı biraz zorlaştırabilir; bu nedenle lubridate her zaman saniye kullanan bir alternatif sağlar: süre.
as.duration(h_age)
#> [1] "1478736000s (~46.86 years)"Süreler çeşitli kullanışlı oluşturucu fonksiyonlarla birlikte gelir:
dseconds(15)
#> [1] "15s"
dminutes(10)
#> [1] "600s (~10 minutes)"
dhours(c(12, 24))
#> [1] "43200s (~12 hours)" "86400s (~1 days)"
ddays(0:5)
#> [1] "0s" "86400s (~1 days)" "172800s (~2 days)"
#> [4] "259200s (~3 days)" "345600s (~4 days)" "432000s (~5 days)"
dweeks(3)
#> [1] "1814400s (~3 weeks)"
dyears(1)
#> [1] "31557600s (~1 years)"Süreler zaman aralığını her zaman saniye cinsinden kaydeder. Daha büyük birimler dakika, saat, gün, hafta ve yılların saniyeye dönüştürülmesiyle oluşturulur: Bir dakikada 60 saniye, bir saatte 60 dakika, bir günde 24 saat ve bir haftada 7 gün vardır. Daha büyük zaman birimleri daha sorunludur. Bir yıl, yıl başına “ortalama” gün sayısını, yani 365,25’i kullanır. Değişkenlik çok fazla olduğu için bir ayı süreye dönüştürmenin yolu yoktur.
Süreleri toplayabilir ve çarpabilirsiniz:
Tarihlere süre ekleyebilir ve tarihlerden süre çıkarabilirsiniz:
Ancak süreler kesin bir saniye sayısını temsil ettiğinden bazen beklenmedik bir sonuç alabilirsiniz:
8 Mart saat 01.00’den bir gün sonrası neden 9 Mart saat 02.00’dir? Tarihe dikkatle bakarsanız saat diliminin de değiştiğini fark edebilirsiniz. Yaz saati uygulaması 8 Mart’ta başladığı için o gün yalnızca 23 saattir; dolayısıyla tam bir güne karşılık gelen saniyeyi eklediğimizde farklı bir saate ulaşırız.
17.4.2 Dönemler
Bu sorunu çözmek için lubridate dönemleri sağlar. Dönemler zaman aralıklarıdır ancak saniye cinsinden sabit uzunlukları yoktur; bunun yerine gün ve ay gibi “insani” zaman birimleriyle çalışırlar. Bu sayede daha sezgisel davranabilirler:
one_am
#> [1] "2026-03-08 01:00:00 EST"
one_am + days(1)
#> [1] "2026-03-09 01:00:00 EDT"Süreler gibi dönemler de çeşitli kullanışlı oluşturucu fonksiyonlarla oluşturulabilir.
Dönemleri toplayabilir ve çarpabilirsiniz:
Elbette dönemleri tarihlere de ekleyebilirsiniz. Dönemlerin beklediğiniz sonucu verme olasılığı sürelere göre daha yüksektir:
Uçuş tarihlerimizle ilgili bir tuhaflığı düzeltmek için dönemleri kullanalım. Bazı uçaklar New York’tan kalkmadan önce varış noktalarına ulaşmış gibi görünmektedir.
flights_dt |>
filter(arr_time < dep_time)
#> # A tibble: 10,633 × 9
#> origin dest dep_delay arr_delay dep_time sched_dep_time
#> <chr> <chr> <dbl> <dbl> <dttm> <dttm>
#> 1 EWR BQN 9 -4 2013-01-01 19:29:00 2013-01-01 19:20:00
#> 2 JFK DFW 59 NA 2013-01-01 19:39:00 2013-01-01 18:40:00
#> 3 EWR TPA -2 9 2013-01-01 20:58:00 2013-01-01 21:00:00
#> 4 EWR SJU -6 -12 2013-01-01 21:02:00 2013-01-01 21:08:00
#> 5 EWR SFO 11 -14 2013-01-01 21:08:00 2013-01-01 20:57:00
#> 6 LGA FLL -10 -2 2013-01-01 21:20:00 2013-01-01 21:30:00
#> # ℹ 10,627 more rows
#> # ℹ 3 more variables: arr_time <dttm>, sched_arr_time <dttm>, …Bunlar gece boyunca süren uçuşlardır. Hem kalkış hem de varış saatleri için aynı tarih bilgisini kullandık ancak bu uçuşlar ertesi gün varmıştır. Her gece uçuşunun varış saatine days(1) ekleyerek bunu düzeltebiliriz.
Artık tüm uçuşlarımız fizik yasalarına uyuyor.
flights_dt |>
filter(arr_time < dep_time)
#> # A tibble: 0 × 10
#> # ℹ 10 variables: origin <chr>, dest <chr>, dep_delay <dbl>,
#> # arr_delay <dbl>, dep_time <dttm>, sched_dep_time <dttm>, …17.4.3 Aralıklar
dyears(1) / ddays(365) ne döndürür? Tam olarak bir değildir; çünkü dyears() ortalama bir yıldaki saniye sayısı, yani 365,25 gün olarak tanımlanır.
Peki years(1) / days(1) ne döndürür? Yıl 2015 ise 365, 2016 ise 366 döndürmelidir! lubridate’in tek ve kesin bir yanıt vermesi için yeterli bilgi yoktur. Bunun yerine bir tahmin verir:
Daha doğru bir ölçüm istiyorsanız bir aralık kullanmanız gerekir. Aralık, başlangıç ve bitiş tarih-saatlerinden oluşan bir çifttir; onu başlangıç noktası bulunan bir süre olarak da düşünebilirsiniz.
start %--% end yazarak bir aralık oluşturabilirsiniz:
Ardından yılda kaç gün bulunduğunu öğrenmek için bunu days() değerine bölebilirsiniz:
17.4.4 Alıştırmalar
days(!overnight)vedays(overnight)ifadelerini R öğrenmeye yeni başlamış birine açıklayın. Bilmeniz gereken temel gerçek nedir?2015 yılındaki her ayın ilk gününü veren bir tarih vektörü oluşturun. Geçerli yıldaki her ayın ilk gününü veren bir tarih vektörü oluşturun.
Doğum gününüzü tarih olarak alıp yaşınızı yıl cinsinden döndüren bir fonksiyon yazın.
17.5 Saat dilimleri
Saat dilimleri jeopolitik oluşumlarla etkileşimleri nedeniyle son derece karmaşık bir konudur. Neyse ki ayrıntıların tümü veri analizi için önemli olmadığından hepsine girmemiz gerekmiyor; ancak doğrudan ele almamız gereken birkaç güçlük var.
İlk güçlük, saat dilimlerinin günlük adlarının çoğunlukla belirsiz olmasıdır. Örneğin Amerikalıysanız EST’yi, yani Eastern Standard Time’ı muhtemelen biliyorsunuzdur. Ancak hem Avustralya hem de Kanada’da EST adlı saat dilimleri vardır! R, karışıklığı önlemek için uluslararası standart IANA saat dilimlerini kullanır. Bunlar genellikle {kıta}/{şehir} ya da {okyanus}/{şehir} biçimindeki tutarlı {bölge}/{konum} adlandırma düzenini kullanır. Örnekler arasında “America/New_York”, “Europe/Paris” ve “Pacific/Auckland” bulunur.
Saat dilimlerini genellikle bir ülke veya ülke içindeki bölgeyle ilişkilendirdiğiniz hâlde adlarda neden şehir kullanıldığını merak edebilirsiniz. Bunun nedeni IANA veritabanının onlarca yıllık saat dilimi kurallarını kaydetmek zorunda olmasıdır. On yıllar içinde ülkeler oldukça sık ad değiştirir (veya bölünür) ancak şehir adları genellikle aynı kalır. Bir başka sorun, adın yalnızca güncel davranışı değil bütün tarihçeyi yansıtması gerektiğidir. Örneğin hem “America/New_York” hem de “America/Detroit” saat dilimleri vardır. İki şehir de günümüzde Eastern Standard Time’ı kullanır; ancak Detroit’in bulunduğu Michigan eyaleti 1969-1972 yıllarında yaz saati uygulamasını izlemediğinden farklı bir ada ihtiyaç duyar. Bu öykülerden bazılarını okumak için ham saat dilimi veritabanına (https://www.iana.org/time-zones) göz atmaya değer!
R’ın geçerli saat diliminizin ne olduğunu düşündüğünü Sys.timezone() ile öğrenebilirsiniz:
Sys.timezone()
#> [1] "UTC"(R bilmiyorsa NA alırsınız.)
Tüm saat dilimi adlarının eksiksiz listesini OlsonNames() ile görebilirsiniz:
length(OlsonNames())
#> [1] 598
head(OlsonNames())
#> [1] "Africa/Abidjan" "Africa/Accra" "Africa/Addis_Ababa"
#> [4] "Africa/Algiers" "Africa/Asmara" "Africa/Asmera"R’da saat dilimi, tarih-saatin yalnızca yazdırılmasını denetleyen bir niteliğidir. Örneğin şu üç nesne zamandaki aynı anı temsil eder:
Çıkarma işlemiyle aynı an olduklarını doğrulayabilirsiniz:
x1 - x2
#> Time difference of 0 secs
x1 - x3
#> Time difference of 0 secsAksi belirtilmedikçe lubridate her zaman UTC kullanır. UTC (Coordinated Universal Time), bilim topluluğunun kullandığı standart saat dilimidir ve yaklaşık olarak GMT’ye (Greenwich Mean Time) eşdeğerdir. Yaz saati uygulaması olmadığı için hesaplamalarda kullanışlı bir gösterimdir. c() gibi tarih-saatleri birleştiren işlemler çoğu zaman saat dilimini kaldırır. Bu durumda tarih-saatler ilk öğenin saat diliminde görüntülenir:
x4 <- c(x1, x2, x3)
x4
#> [1] "2024-06-01 12:00:00 EDT" "2024-06-01 12:00:00 EDT"
#> [3] "2024-06-01 12:00:00 EDT"Saat dilimini iki şekilde değiştirebilirsiniz:
-
Zamandaki anı aynı tutup görüntülenme biçimini değiştirin. An doğru olduğunda ancak daha doğal bir gösterim istediğinizde bunu kullanın.
x4a <- with_tz(x4, tzone = "Australia/Lord_Howe") x4a #> [1] "2024-06-02 02:30:00 +1030" "2024-06-02 02:30:00 +1030" #> [3] "2024-06-02 02:30:00 +1030" x4a - x4 #> Time differences in secs #> [1] 0 0 0(Bu aynı zamanda saat dilimlerinin başka bir güçlüğünü gösterir: Saat farklarının tümü tam sayı değildir!)
-
Altta yatan zaman anını değiştirin. Yanlış saat dilimiyle etiketlenmiş bir anınız olduğunda ve bunu düzeltmeniz gerektiğinde kullanın.
x4b <- force_tz(x4, tzone = "Australia/Lord_Howe") x4b #> [1] "2024-06-01 12:00:00 +1030" "2024-06-01 12:00:00 +1030" #> [3] "2024-06-01 12:00:00 +1030" x4b - x4 #> Time differences in hours #> [1] -14.5 -14.5 -14.5
17.6 Özet
Bu bölüm tarih-saat verileriyle çalışmanıza yardımcı olmak için lubridate’in sunduğu araçları tanıttı. Tarih ve saatlerle çalışmak gereğinden zor görünebilir; ancak umarız bu bölüm bunun nedenini görmenizi sağlamıştır: Tarih-saatler ilk bakışta göründüğünden daha karmaşıktır ve olası her durumu ele almak bu karmaşıklığı artırır. Verileriniz hiçbir zaman yaz saati sınırını aşmasa veya artık yıl içermese bile fonksiyonların bu durumları ele alabilmesi gerekir.
Bir sonraki bölüm eksik değerleri topluca ele alacak. Onları birkaç yerde gördünüz ve kendi analizlerinizde de kuşkusuz karşılaştınız; artık eksik değerleri ele almak için kullanışlı tekniklerden oluşan bir araç çantası sunmanın zamanı geldi.
Bir yıl 4’e tam bölünüyorsa artık yıldır; 100’e de tam bölünüyorsa değildir, ancak 400’e de tam bölünüyorsa yine artık yıldır. Başka bir deyişle her 400 yıllık dönemde 97 artık yıl vardır.↩︎
UTC’nin açılımını merak edebilirsiniz. Bu kısaltma İngilizce “Coordinated Universal Time” ile Fransızca “Temps Universel Coordonné” arasında bir uzlaşmadır.↩︎
Boylam sistemini hangi ülkenin geliştirdiğini tahmin edene ödül yok.↩︎
