readr のロケールの目標は、言語や地域によって異なる共通のオプションをカプセル化することです。これには以下のものが含まれます。
(厳密に言うと、これらは通常の技術的な意味でのロケールではありません。タイムゾーンとエンコーディングに関する情報も含まれているからです。)
新しいロケールを作成するには、 locale()
関数を使用します。
locale()
#> <locale>
#> Numbers: 123,456.78
#> Formats: %AD / %AT
#> Timezone: UTC
#> Encoding: UTF-8
#> <date_names>
#> Days: Sunday (Sun), Monday (Mon), Tuesday (Tue), Wednesday (Wed), Thursday
#> (Thu), Friday (Fri), Saturday (Sat)
#> Months: January (Jan), February (Feb), March (Mar), April (Apr), May (May),
#> June (Jun), July (Jul), August (Aug), September (Sep), October
#> (Oct), November (Nov), December (Dec)
#> AM/PM: AM/PM
この vignette の残りの部分では、それぞれのオプションが何をするのかについて説明します。
readr のすべてのパース関数は locale
引数をとります。ほとんどの場合、 read_csv()
や read_fwf()
、 read_table()
で使用することになるでしょう。Readrはシステム間で同じように動作するように設計されているので、デフォルトのロケールはRと同じく英語中心です。英語圏でない場合は、デフォルトを上書きしなければならないので、最初のインポートが少し難しくなります。しかし、その見返りは大きく、自分のコードを共有し、他のどのシステムでも動作することを知ることができます。Base Rは異なる哲学を持っています。システムのデフォルトを使用するため、典型的なデータのインポートは少し簡単ですが、コードの共有は難しくなります。
この vignette では read_csv()
やフィールドを使ったロケールの使い方を説明するのではなく、 parse_*()
関数を使うことにします。これらはディスク上のファイルではなく文字ベクトルで動作するので、例で使うには簡単です。また、カスタムパースを行う必要がある場合には、それ自体も役に立ちます。データフレームに複数のパーサを適用する必要がある場合は、 type_convert()
を参照してください。
locale()
の最初の引数は date_names
で、月と日の名前にどのような値を使用するかを制御します。これを指定する最も簡単な方法は、ISO 639 の言語コードを使用することです。
locale("ko") # Korean
#> <locale>
#> Numbers: 123,456.78
#> Formats: %AD / %AT
#> Timezone: UTC
#> Encoding: UTF-8
#> <date_names>
#> Days: 일요일 (일), 월요일 (월), 화요일 (화), 수요일 (수), 목요일 (목), 금요일
#> (금), 토요일 (토)
#> Months: 1월, 2월, 3월, 4월, 5월, 6월, 7월, 8월, 9월, 10월, 11월, 12월
#> AM/PM: 오전/오후
locale("fr") # French
#> <locale>
#> Numbers: 123,456.78
#> Formats: %AD / %AT
#> Timezone: UTC
#> Encoding: UTF-8
#> <date_names>
#> Days: dimanche (dim.), lundi (lun.), mardi (mar.), mercredi (mer.), jeudi
#> (jeu.), vendredi (ven.), samedi (sam.)
#> Months: janvier (janv.), février (févr.), mars (mars), avril (avr.), mai
#> (mai), juin (juin), juillet (juil.), août (août), septembre
#> (sept.), octobre (oct.), novembre (nov.), décembre (déc.)
#> AM/PM: AM/PM
もしあなたの言語のコードをまだ知らないのであれば、Wikipediaに良いリストがあります。現在、readrでは 185 の言語が利用可能です。date_names_langs()
を使えば、それらすべてをリストアップすることができます。
ロケールを指定することで、他の言語で書かれた日付をパースすることができます。
parse_date("1 janvier 2015", "%d %B %Y", locale = locale("fr"))
#> [1] "2015-01-01"
parse_date("14 oct. 1979", "%d %b %Y", locale = locale("fr"))
#> [1] "1979-10-14"
多くの言語では、ASCIIとして保存できるように発音区分が削除されていることがよくあります。これをロケールに伝えるには、 asciify
オプションを使用します。
parse_date("1 août 2015", "%d %B %Y", locale = locale("fr"))
#> [1] "2015-08-01"
parse_date("1 aout 2015", "%d %B %Y", locale = locale("fr", asciify = TRUE))
#> [1] "2015-08-01"
翻訳の質は、特に希少な言語では、ばらつきがあることに注意してください。もし、翻訳があなたのデータにとって適切でないことがわかったら、 date_names()
を使って独自のものを作成することができます。次の例では、Māori の日付の名前を持つロケールを作成しています。
<- locale(date_names(
maori day = c("Rātapu", "Rāhina", "Rātū", "Rāapa", "Rāpare", "Rāmere", "Rāhoroi"),
mon = c("Kohi-tātea", "Hui-tanguru", "Poutū-te-rangi", "Paenga-whāwhā",
"Haratua", "Pipiri", "Hōngongoi", "Here-turi-kōkā", "Mahuru",
"Whiringa-ā-nuku", "Whiringa-ā-rangi", "Hakihea")
))
特に指定がない限り、readr は時刻が UTC(協定世界時)であると仮定します(これはGMTの後継で、ほとんどすべての意図で同じものとみなせます)。UTCはサマータイムがないため、データに最も適しており、潜在的な問題を回避することができます。もしあなたのデータがまだ UTC でないなら、ロケールに tz
を指定する必要があります。
parse_datetime("2001-10-10 20:10")
#> [1] "2001-10-10 20:10:00 UTC"
parse_datetime("2001-10-10 20:10", locale = locale(tz = "Pacific/Auckland"))
#> [1] "2001-10-10 20:10:00 NZDT"
parse_datetime("2001-10-10 20:10", locale = locale(tz = "Europe/Dublin"))
#> [1] "2001-10-10 20:10:00 IST"
タイムゾーンの完全なリストは OlsonNames()
で見ることができます。
もしあなたがアメリカ人なら、“EST” はカナダのタイムゾーンであり、サマータイムがないことに注意してください。これは東部標準時ではありません! その代わり、次のようにしてください。
(同じ規則に従わない、より小さな地域向けのより具体的なタイムゾーンがあることに注意してください。例えば、“US/Arizona”は、ほとんど山岳時間に従っていますが、サマータイムはありません。歴史的なデータを扱う場合は、「America/North_Dakota/New_Salem」のようなさらに細かいタイムゾーンが必要かもしれません - これが最も正確なタイムゾーンを得ることができます。)
これらはデフォルトとしてのみ使用されることに注意してください。もし個々の時間にタイムゾーンがあり、“%Z” (名前として、たとえば “America/Chicago”) や “%z” (UTC からのオフセットとして、たとえば “+0800”) を使っているなら、それらはデフォルトをオーバーライドします。現在のところ、米国の略語を使用した時刻を解析する良い方法はありません。
R上で日付を取得した後、タイムゾーンを変更すると印刷される表現が変わるだけで、同じ時刻を表すことに変わりはないことに注意してください。UTCでないデータを読み込んで、それをUTCとして表示させたい場合は、次のコードを試してみてください。
<- sapply(df, inherits, "POSIXct")
is_datetime <- lapply(df[is_datetime], function(x) {
df[is_datetime] attr(x, "tzone") <- "UTC"
x })
ロケールは、日付と時刻のデフォルトフォーマットも提供します。日付の書式は、列の種類を推測する際に使用されます。デフォルトの日付書式は %AD
で、これは柔軟な YMD パーサーです (?parse_date
を参照)。
str(parse_guess("2010-10-10"))
#> Date[1:1], format: "2010-10-10"
str(parse_guess("2010/10/10"))
#> Date[1:1], format: "2010-10-10"
アメリカ人であれば、非論理的な日付システムを使いたいかもしれません。
str(parse_guess("01/31/2013"))
#> chr "01/31/2013"
str(parse_guess("01/31/2013", locale = locale(date_format = "%m/%d/%Y")))
#> Date[1:1], format: "2013-01-31"
時刻の書式は、列の型を推測する際にも使用されます。デフォルトの時間フォーマットは %AT
で、これは柔軟な HMS パーサーです (?parse_time
を参照)。
str(parse_guess("17:55:14"))
#> 'hms' num 17:55:14
#> - attr(*, "units")= chr "secs"
str(parse_guess("5:55:14 PM"))
#> 'hms' num 17:55:14
#> - attr(*, "units")= chr "secs"
# Example of a non-standard time
str(parse_guess("h5m55s14 PM"))
#> chr "h5m55s14 PM"
str(parse_guess("h5m55s14 PM", locale = locale(time_format = "h%Hm%Ms%S %p")))
#> 'hms' num 17:55:14
#> - attr(*, "units")= chr "secs"
readr が提供する関数は、すべて UTF-8 でエンコードされた文字列を生成します。このエンコーディングは、さまざまな設定において良い結果をもたらす可能性が高いものです。デフォルトでは、readr は入力も UTF-8 であると仮定しています。しかし、特に古いデータセットを扱っているときには、そうでない可能性が高いでしょう。
次のコードは、エンコーディングの問題を示しています。
library(stringi)
<- "Émigré cause célèbre déjà vu.\n"
x <- stri_conv(x, "UTF-8", "latin1")
y
# These strings look like they're identical:
x
yidentical(x, y)
# But they have difference encodings:
Encoding(x)
Encoding(y)
# That means while they print the same, their raw (binary)
# representation is actually quite different:
charToRaw(x)
charToRaw(y)
# readr expects strings to be encoded as UTF-8. If they're
# not, you'll get weird characters
parse_character(x)
parse_character(y)
# If you know the encoding, supply it:
parse_character(y, locale = locale(encoding = "latin1"))
ファイルがどのようなエンコーディングを使っているかわからない場合は、 guess_encoding()
を試してみてください。100%完璧ではありませんが(基本的に発見的なので)、少なくとも正しい方向を示してくれるはずです。
guess_encoding(x)
guess_encoding(y)
# Note that the first guess produces a valid string, but isn't correct:
parse_character(y, locale = locale(encoding = "ISO-8859-2"))
# But ISO-8859-1 is another name for latin1
parse_character(y, locale = locale(encoding = "ISO-8859-1"))
国によって、小数点を使うところと、小数点のカンマを使うところがあります。decimal_mark
オプションは、readr が2進数をパースするときにどちらを使用するかを制御します。
parse_double("1,23", locale = locale(decimal_mark = ","))
#> [1] 1.23
さらに、大きな数字を書き出すときには、1,000,000
, 1.000.000
, 1 000
, または 1'000'000
とすることがあります。グループ化マークは、より柔軟な数値パーサーでは無視されます。
parse_number("$1,234.56")
#> [1] 1234.56
parse_number("$1.234,56",
locale = locale(decimal_mark = ",", grouping_mark = ".")
)#> [1] 1234.56
# readr is smart enough to guess that if you're using , for decimals then
# you're probably using . for grouping:
parse_number("$1.234,56", locale = locale(decimal_mark = ","))
#> [1] 1234.56