R入門
tidyverse
最終更新:
r-intro
目次
- 目次
-
tibble
- 基本操作
- tibbleから条件に一致する行を抜き出す
- tibbleから指定の列だけをベクトルで抜き出す
- tibbleで特定の列の集計を行う
- tibbleを任意の列のみのtibbleに変換する
- tibbleで様々な文字コードのCSVファイルを読み込む
- tibbleの行の並び順を任意の列で替える
- tibbleに新しい列を追加する
- tibbleに既存の列の値を利用した新しい列を追加する
- 正規表現を使用してtibbleから条件に一致する行を抜き出す
- 特定の列の値でtibbleの行を並び替える
- tibbleの列名を変える
- tibbleを特定の列だけのtibbleに変換する
- tibbleの列の順番を並び替える
- tibbleの別の列の値を条件に使用して指定の列の値を変更する
- 特定の列の値を基準にして2つのtibbleが結合できるか否か確認する
- tibbleから指定の列が重複する行を削除する
- tibbleから列の値が重複している行を抽出する
- 連結
- 結合
- 集計
- その他
- テキストファイルの読み込み
- テキストファイルへの書き込み
- その他
tibble
基本操作
tibbleを使う
tibbleパッケージをインストールする。
> library(tibble)
data.frameと同じように扱える。
> s <- c("A", "B", "CD")
> d <- c(1, 2, 9)
> ti <- tibble(s, d)
> ti
# A tibble: 3 x 2
s d
<chr> <dbl>
1 A 1
2 B 2
3 CD 9
> ti[1, 2]
# A tibble: 1 x 1
d
<dbl>
1 1
> ti[3, 1]
# A tibble: 1 x 1
s
<chr>
1 CD
> sum(ti[, 2])
[1] 12
tibbleを作成する
tibble関数を使う。tibbleはデータフレームに類似した機能を提供するが、データフレームよりもいろいろと便利な機能を提供する。
> library(tibble)
> no <- 1:4
> name <- c("AB", "12", "あい", "阿井")
> weight <- c(1.2, 2.3, 3.4, 4.5)
> tbl <- tibble(no, name, weight)
> print(tbl)
# A tibble: 4 x 3
no name weight
<int> <chr> <dbl>
1 1 AB 1.2
2 2 12 2.3
3 3 あい 3.4
4 4 阿井 4.5
> dim(tbl)
[1] 4 3
> dim(tbl)[2]
[1] 3
> tbl[1, 2]
# A tibble: 1 x 1
name
<chr>
1 AB
> tbl[2, 3]
# A tibble: 1 x 1
weight
<dbl>
1 2.3
> tbl[3, ]
# A tibble: 1 x 3
no name weight
<int> <chr> <dbl>
1 3 あい 3.4
> tbl[, 3]
# A tibble: 4 x 1
weight
<dbl>
1 1.2
2 2.3
3 3.4
4 4.5
> tbl$name
[1] "AB" "12" "あい" "阿井"
> tbl$name[3]
[1] "あい"
データフレームをtibbleに変換する
as_tibble関数を使う。
> library(tibble)
> no <- 1:4
> name <- c("AB", "12", "あい", "阿井")
> weight <- c(1.2, 2.3, 3.4, 4.5)
> dtf <- data.frame(no, name, weight)
> print(dtf)
no name weight
1 1 AB 1.2
2 2 12 2.3
3 3 あい 3.4
4 4 阿井 4.5
> tbl <- as_tibble(dtf)
> print(tbl)
# A tibble: 4 x 3
no name weight
<int> <chr> <dbl>
1 1 AB 1.2
2 2 12 2.3
3 3 あい 3.4
4 4 阿井 4.5
> class(dtf)
[1] "data.frame"
> class(tbl)
[1] "tbl_df" "tbl" "data.frame"
tibbleの列名を変更する
rename関数かcolnames関数を使う。rename関数は任意の列名を変更することができる。また、渡されたtibbleの列名を変更するだけである。一方、colnames関数はすべてを一括で変更することしかできず、また、指定するtibbleの列名を強制的に変更する。
> library(tidyverse)
> tib <- tibble(
+ no = c(8, 30, 58),
+ name = c("ウオッカ", "ライスシャワー", "メイショウドトウ"),
+ seiyu = c("大橋彩香", "石見舞菜香", "和多田美咲")
+ )
> print(tib %>% as.data.frame())
no name seiyu
1 8 ウオッカ 大橋彩香
2 30 ライスシャワー 石見舞菜香
3 58 メイショウドトウ 和多田美咲
> tib2 <- tib %>% rename(id = no, voiceactress = seiyu)
> print(tib2 %>% as.data.frame())
id name voiceactress
1 8 ウオッカ 大橋彩香
2 30 ライスシャワー 石見舞菜香
3 58 メイショウドトウ 和多田美咲
> tib3 <- tib
> colnames(tib3) <- c("n", "horse", "cv")
> print(tib3 %>% as.data.frame())
n horse cv
1 8 ウオッカ 大橋彩香
2 30 ライスシャワー 石見舞菜香
3 58 メイショウドトウ 和多田美咲
tibbleで特殊な列名を使用して操作する
例えばASCIIの0~9で始まる名前は通常は列名に使用できないが、バックティック(`)で挟むと使用することができるようになる。
> library(tidyverse)
> tib <- tibble(21世紀 = 1:4)
エラー: 想定外のシンボルです ( "tib <- tibble(21世紀" の)
> tib <- tibble(`21世紀` = 1:4)
> tib %>% as.data.frame()
21世紀
1 1
2 2
3 3
4 4
> tib %>% filter(`21世紀` >= 3) %>% as.data.frame()
21世紀
1 3
2 4
tibbleから条件に一致する行を抜き出す
tidyverse(dplyr)パッケージに含まれるfilter関数を使う。以下のような中身のCSVファイルをmeibo.csvと保存しておく。
no, sei, mei, age, weight
1, あいう, えお, 11, 101.1
2, かきく, けこ, 22, 202.2
3, さしす, せそ, 22, 303.3
4, あいう, けこ, 33, 404.4
meibo.csvを読み込んで、条件を指定して行を抜き出してみる。
> library(tidyverse)
> tbl <- read_csv("meibo.csv", show_col_types = FALSE, progress = FALSE)
> print(tbl)
# A tibble: 4 × 5
no sei mei age weight
<dbl> <chr> <chr> <dbl> <dbl>
1 1 あいう えお 11 101.
2 2 かきく けこ 22 202.
3 3 さしす せそ 22 303.
4 4 あいう けこ 33 404.
> filter(tbl, sei == "あいう")
# A tibble: 2 × 5
no sei mei age weight
<dbl> <chr> <chr> <dbl> <dbl>
1 1 あいう えお 11 101.
2 4 あいう けこ 33 404.
> filter(tbl, sei == "あいう", mei == "けこ")
# A tibble: 1 × 5
no sei mei age weight
<dbl> <chr> <chr> <dbl> <dbl>
1 4 あいう けこ 33 404.
> filter(tbl, sei == "あいう" & mei == "けこ")
# A tibble: 1 × 5
no sei mei age weight
<dbl> <chr> <chr> <dbl> <dbl>
1 4 あいう けこ 33 404.
> tbl %>% filter(age == 22)
# A tibble: 2 × 5
no sei mei age weight
<dbl> <chr> <chr> <dbl> <dbl>
1 2 かきく けこ 22 202.
2 3 さしす せそ 22 303.
tibbleから指定の列だけをベクトルで抜き出す
tidyverse(dplyr)パッケージに含まれるpull関数を使う。以下のような中身のCSVファイルをmeibo.csvと保存しておく。
no, sei, mei, age, weight
1, あいう, えお, 11, 101.1
2, かきく, けこ, 22, 202.2
3, さしす, せそ, 22, 303.3
4, あいう, けこ, 33, 404.4
meibo.csvを読み込んで、条件を指定して行を抜き出してみる。%>%演算子も使える。
> library(tidyverse)
> tbl <- read_csv("meibo.csv", show_col_types = FALSE, progress = FALSE)
> pull(tbl, 2)
[1] "あいう" "かきく" "さしす" "あいう"
> pull(tbl, mei)
[1] "えお" "けこ" "せそ" "けこ"
> tbl %>% pull(4)
[1] 11 22 22 33
> tbl %>% pull(weight)
[1] 101.1 202.2 303.3 404.4
[[ ]]記号や$記号を使う場合と全く同じである。
> tbl[[4]]
[1] 11 22 22 33
> tbl$weight
[1] 101.1 202.2 303.3 404.4
tibbleで特定の列の集計を行う
group_by関数とsummarize関数を組み合わせて使う。以下の例ではgroup_by関数にclass列を指定し、class列ごとのweightの平均を求めている。簡潔な表示にするため、表示する際にはデータフレームに変換している。group_by関数を使った後の出力を見ると「Groups: class [3]」と表示されており、内部的にはグループ化された異なるオブジェクトであることがわかる。
> library(tidyverse)
> no <- 1:6
> name <- c("AB", "CD", "EF", "GH", "IJ", "KL")
> weight <- c(11, 22, 33, 44, 55, 66)
> class <- c("a", "b", "c", "a", "a", "b")
> tbl <- tibble(no, name, weight, class)
> as.data.frame(tbl)
no name weight class
1 1 AB 11 a
2 2 CD 22 b
3 3 EF 33 c
4 4 GH 44 a
5 5 IJ 55 a
6 6 KL 66 b
> as.data.frame(tbl %>% group_by(class) %>% summarize(weight = mean(weight)))
class weight
1 a 36.66667
2 b 44.00000
3 c 33.00000
> tbl %>% group_by(class)
# A tibble: 6 × 4
# Groups: class [3]
no name weight class
(以下、表示省略)
tibbleを任意の列のみのtibbleに変換する
tidyverse(dplyr)パッケージのselect関数を使う。以下、あらかじめ用意してあるtibbleを使用した動作例。列名を指定するとその列だけを含むtibble(ベクトルではない!)に変換する。:(コロン)を使うとそれを両端としたその範囲の列すべてを抜き出す。接頭辞として-(マイナス)を付けるとその列を含まないという意味になる。列の指定には列名と番号(1~)が使える。等号(=)を使うことで列名を変えて取り出すこともできる。
> library(tidyverse)
> tib %>% as.data.frame()
no name prizemoney seiyu dummydate
1 8 ウオッカ 13.0487 大橋彩香 2031-02-03
2 30 ライスシャワー 6.6686 石見舞菜香 2032-11-12
3 45 スーパークリーク 5.5610 優木かな 2033-11-12
4 58 メイショウドトウ 9.2133 和多田美咲 2033-12-31
> tib %>% select(name, seiyu) %>% as.data.frame()
name seiyu
1 ウオッカ 大橋彩香
2 ライスシャワー 石見舞菜香
3 スーパークリーク 優木かな
4 メイショウドトウ 和多田美咲
> tib %>% select(name:seiyu) %>% as.data.frame()
name prizemoney seiyu
1 ウオッカ 13.0487 大橋彩香
2 ライスシャワー 6.6686 石見舞菜香
3 スーパークリーク 5.5610 優木かな
4 メイショウドトウ 9.2133 和多田美咲
> tib %>% select(2, 4) %>% as.data.frame()
name seiyu
1 ウオッカ 大橋彩香
2 ライスシャワー 石見舞菜香
3 スーパークリーク 優木かな
4 メイショウドトウ 和多田美咲
> tib %>% select(2:4) %>% as.data.frame()
name prizemoney seiyu
1 ウオッカ 13.0487 大橋彩香
2 ライスシャワー 6.6686 石見舞菜香
3 スーパークリーク 5.5610 優木かな
4 メイショウドトウ 9.2133 和多田美咲
> tib %>% select(-(no:prizemoney), -dummydate) %>% as.data.frame()
seiyu
1 大橋彩香
2 石見舞菜香
3 優木かな
4 和多田美咲
> tib %>% select(-(1:3), -5) %>% as.data.frame()
seiyu
1 大橋彩香
2 石見舞菜香
3 優木かな
4 和多田美咲
> tib %>% select(name, cv = seiyu) %>% as.data.frame()
name cv
1 ウオッカ 大橋彩香
2 ライスシャワー 石見舞菜香
3 スーパークリーク 優木かな
4 メイショウドトウ 和多田美咲
tibbleを任意の列のみのtibbleに変換する
tidyverse(dplyr)パッケージに含まれるselect関数を使う。以下のような中身のCSVファイルをmeibo.csvと保存しておく。
no, sei, mei, age, weight
1, あいう, えお, 11, 101.1
2, かきく, けこ, 22, 202.2
3, さしす, せそ, 22, 303.3
4, あいう, けこ, 33, 404.4
%>%演算子を使わない場合は、第一引数に変換元のtibbleを指定する。簡潔な表示にするため、tibbleの表示はデータフレームに変換して行っている。
> library(tidyverse)
> tbl <- read_csv("meibo.csv", show_col_types = FALSE, progress = FALSE)
> as.data.frame(select(tbl, no, sei, mei))
no sei mei
1 1 あいう えお
2 2 かきく けこ
3 3 さしす せそ
4 4 あいう けこ
> as.data.frame(tbl %>% select(no, sei, mei))
no sei mei
1 1 あいう えお
2 2 かきく けこ
3 3 さしす せそ
4 4 あいう けこ
tibbleで様々な文字コードのCSVファイルを読み込む
read_csv関数を使う。localeオプションに文字コードを指定する。
最初にPowerShellを使ってカレントディレクトリに、順番にシフトJIS、UTF-8(BOM無し)、UTF-8(BOM付き)、UTF-16(ビッグエンディアン、BOM付き)、UTF-16(リトルエンディアン、BOM付き)のCSVファイルを出力する。PowerShellのコマンドレットはUnicode系は原則BOM付きとなるため、BOM無しのUTF-8の出力にFileクラスのWriteAllLinesメソッドを使用している。
PS > $lines = "1,ABC", "2,abc", "3,あいう"
PS > $odir = (gl).Path
PS > $lines | Out-File -Encoding default ($odir + "\sjis.csv")
PS > [IO.File]::WriteAllLines(($odir + "\utf8nb.csv"), $lines)
PS > $lines | Out-File -Encoding utf8 ($odir + "\utf8wb.csv")
PS > $lines | Out-File -Encoding bigendianunicode ($odir + "\utf16bewb.csv")
PS > $lines | Out-File -Encoding unicode ($odir + "\utf16lewb.csv")
PS > Get-Content .\sjis.csv
1,ABC
2,abc
3,あいう
PS > Get-Content .\utf8nb.csv -Encoding utf8
1,ABC
2,abc
3,あいう
Rを起動してそれぞれread_csv関数で読み込む。localeオプションにそれぞれ文字コードを指定する。UTF-16の場合、「UTF-16」を指定すればバイトオーダーマークからエンディアンを推定して読み込むが、エンディアンを指定することもできる。最後の例のとおりに、エンディアンの指定を間違えると、指定のとおりに読み込もうとして読み込みに失敗する。
簡潔な表示にするため、最初にoptions関数で画面表示に関するオプションを指定し、読み込んだtibbleはデータフレームに変換している。
> options(readr.show_progress = FALSE, readr.show_col_types = FALSE)
> as.data.frame(read_csv("sjis.csv", locale = locale(encoding = "SJIS")))
no name
1 1 ABC
2 2 abc
3 3 あいう
> as.data.frame(read_csv("utf8nb.csv", locale = locale(encoding = "UTF-8")))
no name
1 1 ABC
2 2 abc
3 3 あいう
> as.data.frame(read_csv("utf8wb.csv", locale = locale(encoding = "UTF-8")))
no name
1 1 ABC
2 2 abc
3 3 あいう
> as.data.frame(read_csv("utf16bewb.csv", locale = locale(encoding = "UTF-16")))
no name
1 1 ABC
2 2 abc
3 3 あいう
> as.data.frame(read_csv("utf16lewb.csv", locale = locale(encoding = "UTF-16")))
no name
1 1 ABC
2 2 abc
3 3 あいう
> as.data.frame(read_csv("utf16bewb.csv", locale = locale(encoding = "UTF-16BE")))
no name
1 1 ABC
2 2 abc
3 3 あいう
> as.data.frame(read_csv("utf16lewb.csv", locale = locale(encoding = "UTF-16LE")))
no name
1 1 ABC
2 2 abc
3 3 あいう
> as.data.frame(read_csv("utf16lewb.csv", locale = locale(encoding = "UTF-16BE")))
[1] \ufffe渀漀Ⰰ渀愀洀攀ഀ\u0a00\u3100Ⰰ䄀䈀䌀ഀ\u0a00㈀Ⰰ愀戀挀ഀ\u0a00㌀Ⰰ䈰䐰䘰ഀ\u0a00
<0 行> (または長さ 0 の row.names)
tibbleの行の並び順を任意の列で替える
tidyverse(dplyr)パッケージに含まれるarrange関数を使う。以下のような中身のCSVファイルをmeibo.csvと保存しておく。
no, sei, mei, age, weight
1, あいう, えお, 11, 101.1
2, かきく, けこ, 22, 202.2
3, さしす, せそ, 22, 303.3
4, あいう, けこ, 33, 404.4
列を指定すると、その列で並び順を変える。降順にする場合はdesc関数を使う。以下の例のとおり、複数指定した場合は、指定した列の順に並び替える。%>%演算子を使わない場合は、第一引数に変換元のtibbleを指定する。簡潔な表示にするため、tibbleの表示はデータフレームに変換して行っている。
> library(tidyverse)
> tbl <- read_csv("meibo.csv", show_col_types = FALSE, progress = FALSE)
> as.data.frame(tbl)
no sei mei age weight
1 1 あいう えお 11 101.1
2 2 かきく けこ 22 202.2
3 3 さしす せそ 22 303.3
4 4 あいう けこ 33 404.4
> as.data.frame(tbl %>% arrange(sei))
no sei mei age weight
1 1 あいう えお 11 101.1
2 4 あいう けこ 33 404.4
3 2 かきく けこ 22 202.2
4 3 さしす せそ 22 303.3
> as.data.frame(tbl %>% arrange(sei, desc(age)))
no sei mei age weight
1 4 あいう けこ 33 404.4
2 1 あいう えお 11 101.1
3 2 かきく けこ 22 202.2
4 3 さしす せそ 22 303.3
tibbleに新しい列を追加する
add_column関数を使う。.afterオプション(.beforeオプションもある)を使うと任意の位置に追加することができる。
> library(tibble)
> no <- 1:2
> name <- c("セナディア", "イレイナ")
> tib <- tibble(no, name)
> tib |> as.data.frame()
no name
1 1 セナディア
2 2 イレイナ
> seiyu <- c("鈴木みのり", "本渡楓")
> tib <- tib |> add_column(seiyu = seiyu)
> tib |> as.data.frame()
no name seiyu
1 1 セナディア 鈴木みのり
2 2 イレイナ 本渡楓
> tib <- tib |> add_column(seiyu2 = seiyu, .after = no)
> tib |> as.data.frame()
no seiyu2 name seiyu
1 1 鈴木みのり セナディア 鈴木みのり
2 2 本渡楓 イレイナ 本渡楓
tibbleに既存の列の値を利用した新しい列を追加する
mutate関数を使う。なお、簡潔な表示にするため、tibbleの表示はデータフレームに変換して行っている。
> library(tidyverse)
> tbl <- read_csv("meibo.csv", show_col_types = FALSE, progress = FALSE)
> as.data.frame(tbl)
no sei mei age weight
1 1 あいう えお 11 101.1
2 2 かきく けこ 22 202.2
3 3 さしす せそ 22 303.3
4 4 あいう けこ 33 404.4
> as.data.frame(mutate(tbl, age2 = age * 2, seimei = paste0(sei, mei)))
no sei mei age weight age2 seimei
1 1 あいう えお 11 101.1 22 あいうえお
2 2 かきく けこ 22 202.2 44 かきくけこ
3 3 さしす せそ 22 303.3 44 さしすせそ
4 4 あいう けこ 33 404.4 66 あいうけこ
> as.data.frame(tbl %>% mutate(seibetsu = c("F", "M", "F", "F")))
no sei mei age weight seibetsu
1 1 あいう えお 11 101.1 F
2 2 かきく けこ 22 202.2 M
3 3 さしす せそ 22 303.3 F
4 4 あいう けこ 33 404.4 F
正規表現を使用してtibbleから条件に一致する行を抜き出す
tidyverse(dplyr、stringr)パッケージに含まれるfilter関数とstr_detect関数を組み合わせて使う。以下の例では、簡潔な表示にするために表示の際にtibbleをデータフレームに変換している。
> library(tidyverse)
> no <- 1:5
> mei <- c("カナメ", "フレイア", "美雲", "マキナ", "レイナ")
> sei <- c("バッカニア", "ヴィオン", "ギンヌメール", "中島", "プラウラー")
> fname <- c("Kaname", "Freyja", "Mikumo", "Makina", "Reina")
> lname <- c("Buccaneer", "Wion", "Guynemer", "Nakajima", "Prowler")
> seiyu <- c("安野希世乃", "鈴木みのり", "小清水亜美", "西田望見", "東山奈央")
> tib <- tibble(no, mei, sei, fname, lname, seiyu)
> print(as.data.frame(tib))
no mei sei fname lname seiyu
1 1 カナメ バッカニア Kaname Buccaneer 安野希世乃
2 2 フレイア ヴィオン Freyja Wion 鈴木みのり
3 3 美雲 ギンヌメール Mikumo Guynemer 小清水亜美
4 4 マキナ 中島 Makina Nakajima 西田望見
5 5 レイナ プラウラー Reina Prowler 東山奈央
> tib %>% filter(str_detect(mei, "ナ")) %>% as.data.frame()
no mei sei fname lname seiyu
1 1 カナメ バッカニア Kaname Buccaneer 安野希世乃
2 4 マキナ 中島 Makina Nakajima 西田望見
3 5 レイナ プラウラー Reina Prowler 東山奈央
> tib %>% filter(str_detect(mei, "ナ$")) %>% as.data.frame()
no mei sei fname lname seiyu
1 4 マキナ 中島 Makina Nakajima 西田望見
2 5 レイナ プラウラー Reina Prowler 東山奈央
> tib %>% filter(str_detect(mei, "ナ") & str_detect(lname, "er$")) %>% as.data.frame()
no mei sei fname lname seiyu
1 1 カナメ バッカニア Kaname Buccaneer 安野希世乃
2 5 レイナ プラウラー Reina Prowler 東山奈央
特定の列の値でtibbleの行を並び替える
arrange関数を使う。引数に、並び替えの基準にする列を指定する。複数同時に指定できる。デフォルトでは昇順に並び替えられるが、これを降順にする場合は列の指定にdesc関数を指定して指定すればよい。
以下の例では簡潔な表示にするため、表示の際にtibbleはデータフレームに変換している。
> library(tidyverse)
> no <- 1:5
> name <- c("ABC", "ABC", "abc", "123", "あいう")
> age <- 25:21
> tib <- tibble(no, name, age)
> as.data.frame(tib)
no name age
1 1 ABC 25
2 2 ABC 24
3 3 abc 23
4 4 123 22
5 5 あいう 21
> tib %>% arrange(age) %>% as.data.frame()
no name age
1 5 あいう 21
2 4 123 22
3 3 abc 23
4 2 ABC 24
5 1 ABC 25
> tib %>% arrange(name, age) %>% as.data.frame()
no name age
1 4 123 22
2 2 ABC 24
3 1 ABC 25
4 3 abc 23
5 5 あいう 21
> tib %>% arrange(name, desc(age)) %>% as.data.frame()
no name age
1 4 123 22
2 1 ABC 25
3 2 ABC 24
4 3 abc 23
5 5 あいう 21
tibbleの列名を変える
rename関数を使う。引数には、変えたい列を「(新列名)=(旧列名)」と指定する。複数同時に指定できる。
以下の例では簡潔な表示にするため、表示の際にtibbleはデータフレームに変換している。
> library(tidyverse)
> no <- 1:3
> name <- c("ABC", "abc", "123")
> age <- 23:21
> tib <- tibble(no, name, age)
> tib %>% as.data.frame()
no name age
1 1 ABC 23
2 2 abc 22
3 3 123 21
> tib %>% rename(seimei = name, toshi = age) %>% as.data.frame()
no seimei toshi
1 1 ABC 23
2 2 abc 22
3 3 123 21
tibbleを特定の列だけのtibbleに変換する
select関数を使う。引数に抜き出したい列を指定すればよい。列の指定は列名でも番号(1~)でも指定できる。接頭辞として!を付けるとその列を除くという意味になる。!の指定には列番号にも使える。:(コロン)を使うことで、その列からその列までという範囲指定もできる。
以下の例では簡潔な表示にするため、表示の際にtibbleはデータフレームに変換している。
> library(tidyverse)
> no <- 1:5
> mei <- c("カナメ", "フレイア", "美雲", "マキナ", "レイナ")
> sei <- c("バッカニア", "ヴィオン", "ギンヌメール", "中島", "プラウラー")
> seiyu <- c("安野希世乃", "鈴木みのり", "小清水亜美", "西田望見", "東山奈央")
> tib <- tibble(no, mei, sei, seiyu)
> tib %>% select(mei, sei) %>% as.data.frame()
mei sei
1 カナメ バッカニア
2 フレイア ヴィオン
3 美雲 ギンヌメール
4 マキナ 中島
5 レイナ プラウラー
> tib %>% select(!no) %>% as.data.frame()
mei sei seiyu
1 カナメ バッカニア 安野希世乃
2 フレイア ヴィオン 鈴木みのり
3 美雲 ギンヌメール 小清水亜美
4 マキナ 中島 西田望見
5 レイナ プラウラー 東山奈央
> tib %>% select(2, 3) %>% as.data.frame()
mei sei
1 カナメ バッカニア
2 フレイア ヴィオン
3 美雲 ギンヌメール
4 マキナ 中島
5 レイナ プラウラー
> tib %>% select(!1) %>% as.data.frame()
mei sei seiyu
1 カナメ バッカニア 安野希世乃
2 フレイア ヴィオン 鈴木みのり
3 美雲 ギンヌメール 小清水亜美
4 マキナ 中島 西田望見
5 レイナ プラウラー 東山奈央
> tib %>% select(!(1:3)) %>% as.data.frame()
seiyu
1 安野希世乃
2 鈴木みのり
3 小清水亜美
4 西田望見
5 東山奈央
tibbleの列の順番を並び替える
select関数を使う。引数には並び替えたい順に列名を指定する。すべての列を指定する必要はなく、特定の列だけを指定すると、その順にそれらの列だけからなるtibbleが作成される。引数にeverything関数を指定すると指定した列以外のすべて列という意味になるため、以下の3番目の例のとおり、特定の列だけを前(左側)なり後ろ(右側)なりに移動させたい場合に利用できる。
以下の例では簡潔な表示にするため、表示の際にtibbleはデータフレームに変換している。
> library(tidyverse)
> mei <- c("カナメ", "フレイア", "美雲", "マキナ", "レイナ")
> sei <- c("バッカニア", "ヴィオン", "ギンヌメール", "中島", "プラウラー")
> no <- 1:5
> seiyu <- c("安野希世乃", "鈴木みのり", "小清水亜美", "西田望見", "東山奈央")
> tib <- tibble(no, mei, sei, seiyu)
> as.data.frame(tib)
no mei sei seiyu
1 1 カナメ バッカニア 安野希世乃
2 2 フレイア ヴィオン 鈴木みのり
3 3 美雲 ギンヌメール 小清水亜美
4 4 マキナ 中島 西田望見
5 5 レイナ プラウラー 東山奈央
> tib %>% select(no, seiyu, mei, sei) %>% as.data.frame()
no seiyu mei sei
1 1 安野希世乃 カナメ バッカニア
2 2 鈴木みのり フレイア ヴィオン
3 3 小清水亜美 美雲 ギンヌメール
4 4 西田望見 マキナ 中島
5 5 東山奈央 レイナ プラウラー
> tib %>% select(no, seiyu) %>% as.data.frame()
no seiyu
1 1 安野希世乃
2 2 鈴木みのり
3 3 小清水亜美
4 4 西田望見
5 5 東山奈央
> tib %>% select(no, seiyu, everything()) %>% as.data.frame()
no seiyu mei sei
1 1 安野希世乃 カナメ バッカニア
2 2 鈴木みのり フレイア ヴィオン
3 3 小清水亜美 美雲 ギンヌメール
4 4 西田望見 マキナ 中島
5 5 東山奈央 レイナ プラウラー
tibbleの別の列の値を条件に使用して指定の列の値を変更する
mutate関数とcase_when関数を組み合わせて使う。以下は、次のtibbleについてそのtibbleの別の列の値からそれぞれcv列に値を代入した例。
> library(tidyverse)
> tib %>% as.data.frame()
title no chara cv
1 ウマ娘 30 ライスシャワー NA
2 ウマ娘 45 スーパークリーク NA
3 ウマ娘 58 メイショウドトウ NA
4 ライザのアトリエ2 1 ライザ NA
5 ライザのアトリエ2 2 フィー NA
6 推しの子 6 黒川あかね NA
case_when関数には条件ごとにコンマで区切って「条件式 ~ 代入する値」と指定する。指定した順に評価されて代入される。条件に一致しないものは何もしない。
> tib %>% mutate(cv = case_when(
+ title == "ウマ娘" & chara == "ライスシャワー" ~ "石見舞菜香",
+ chara == "メイショウドトウ" | chara == "フィー" ~ "和多田美咲"
+ )) %>% as.data.frame()
title no chara cv
1 ウマ娘 30 ライスシャワー 石見舞菜香
2 ウマ娘 45 スーパークリーク <NA>
3 ウマ娘 58 メイショウドトウ 和多田美咲
4 ライザのアトリエ2 1 ライザ <NA>
5 ライザのアトリエ2 2 フィー 和多田美咲
6 推しの子 6 黒川あかね <NA>
mutate関数は存在する列を指定するとその列の値を書き換えるが、存在しない列名を指定するとその列を新たに作成する。
> tib %>% mutate(type = case_when(
+ str_detect(title, "^推し") ~ "アニメ",
+ )) %>% as.data.frame()
title no chara cv type
1 ウマ娘 30 ライスシャワー NA <NA>
2 ウマ娘 45 スーパークリーク NA <NA>
3 ウマ娘 58 メイショウドトウ NA <NA>
4 ライザのアトリエ2 1 ライザ NA <NA>
5 ライザのアトリエ2 2 フィー NA <NA>
6 推しの子 6 黒川あかね NA アニメ
case_when関数で指定した条件は指定した順に評価されるため、最後の条件の条件式にTRUEを指定すればif文のelseに相当する動作をさせることができる。
> tib %>% mutate(type = case_when(
+ str_detect(title, "^推し") ~ "アニメ",
+ TRUE ~ "ゲーム"
+ )) %>% as.data.frame()
title no chara cv type
1 ウマ娘 30 ライスシャワー NA ゲーム
2 ウマ娘 45 スーパークリーク NA ゲーム
3 ウマ娘 58 メイショウドトウ NA ゲーム
4 ライザのアトリエ2 1 ライザ NA ゲーム
5 ライザのアトリエ2 2 フィー NA ゲーム
6 推しの子 6 黒川あかね NA アニメ
特定の列の値を基準にして2つのtibbleが結合できるか否か確認する
tidyverse(dplyr)パッケージのsemi_join関数、anti_join関数を使う。基準とする列の指定にはjoin_by関数を使う。以下は、次の2つのtibbleを指定の列(以下の例ではcvとid)の値を基準にして結合できるか否か確認した例。簡潔な表示にするため、表示はすべてデータフレームで行っている。
> chara %>% as.data.frame()
nama title no cv
1 ライスシャワー ウマ娘 30 miwami01
2 スーパークリーク ウマ娘 45 kyuki01
3 メイショウドトウ ウマ娘 58 mwatada01
4 ライザ ライザのアトリエ2 1 ynoguchi01
5 フィー ライザのアトリエ2 2 mwatada01
6 黒川あかね 推しの子 6 miwami01
> seiyu %>% as.data.frame()
id name
1 miwami01 石見舞菜香
2 kyuki01 優木かな
3 mwatada01 和多田美咲
4 machico01 Machico
semi_join関数は、右側に指定の列の値が一致する行がある左側の行を返す。inner_join関数と動作は似ているが、semi_join関数は、結合はせずに結合が可能な左側の行だけを返す。
> chara %>% inner_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
5 黒川あかね 推しの子 6 miwami01 石見舞菜香
> chara %>% semi_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv
1 ライスシャワー ウマ娘 30 miwami01
2 スーパークリーク ウマ娘 45 kyuki01
3 メイショウドトウ ウマ娘 58 mwatada01
4 フィー ライザのアトリエ2 2 mwatada01
5 黒川あかね 推しの子 6 miwami01
anti_join関数は、右側に指定の列の値が一致する行がない左側の行を返す。left_join関数では無理矢理結合され列にNAが代入された行(以下の4行目)だけが返されるが、anti_join関数は結合はせずに左側の行だけを返す。
> chara %>% left_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 ライザ ライザのアトリエ2 1 ynoguchi01 <NA>
5 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
6 黒川あかね 推しの子 6 miwami01 石見舞菜香
> chara %>% anti_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv
1 ライザ ライザのアトリエ2 1 ynoguchi01
tibbleから指定の列が重複する行を削除する
distinct関数を使う。引数に指定した列から重複を取り除いてその列だけを返す。2つ以上同時に指定もできる。
> tib %>% as.data.frame()
title seiyu
1 ウマ娘 大橋彩香
2 ウマ娘 大橋彩香
3 ウマ娘 石見舞菜香
4 ライザのアトリエ2 石見舞菜香
5 推しの子 石見舞菜香
6 ウマ娘 和多田美咲
> tib %>% distinct(title) %>% as.data.frame()
title
1 ウマ娘
2 ライザのアトリエ2
3 推しの子
> tib %>% distinct(seiyu) %>% as.data.frame()
seiyu
1 大橋彩香
2 石見舞菜香
3 和多田美咲
> tib %>% distinct(title, seiyu) %>% as.data.frame()
title seiyu
1 ウマ娘 大橋彩香
2 ウマ娘 石見舞菜香
3 ライザのアトリエ2 石見舞菜香
4 推しの子 石見舞菜香
5 ウマ娘 和多田美咲
tibbleから列の値が重複している行を抽出する
group_by関数で列を指定してグループ化し、filter関数とn関数を組み合わせてグループの行数が2以上の行を表示させればよい。最後の例のとおり、二つ以上の列を同時に指定することもできる。
> library(tidyverse)
> tib %>% as.data.frame()
name seiyu
1 ライスシャワー 石見舞菜香
2 ライスシャワー 石見舞菜香
3 メイショウドトウ 和多田美咲
4 メイショウドトウ (調査中)
5 サクラチヨノオー 野口瑠璃子
> tib %>% group_by(name) %>% filter(n() > 1) %>% as.data.frame()
name seiyu
1 ライスシャワー 石見舞菜香
2 ライスシャワー 石見舞菜香
3 メイショウドトウ 和多田美咲
4 メイショウドトウ (調査中)
> tib %>% group_by(name, seiyu) %>% filter(n() > 1) %>% as.data.frame()
name seiyu
1 ライスシャワー 石見舞菜香
2 ライスシャワー 石見舞菜香
ある列の重複を除いた個数を調べる
group_by関数で列を指定してグループ化し、summarize関数で集計する。集計時にn関数を指定すると、その個数を返す。以下はあらかじめ用意したtibbleで実行した例。
> library(tidyverse)
> tib %>% as.data.frame()
nama title seiyu
1 ライスシャワー ウマ娘 石見舞菜香
2 スーパークリーク ウマ娘 優木かな
3 メイショウドトウ ウマ娘 和多田美咲
4 フィー ライザのアトリエ2 和多田美咲
5 黒川あかね 推しの子 石見舞菜香
> tib %>% group_by(title) %>% summarize(nn = n()) %>% as.data.frame()
title nn
1 ウマ娘 3
2 ライザのアトリエ2 1
3 推しの子 1
> tib %>% group_by(seiyu) %>% summarize(nn = n()) %>% as.data.frame()
seiyu nn
1 優木かな 1
2 和多田美咲 2
3 石見舞菜香 2
グループ化には2つ以上の列を同時に指定することもできる。
> tib2 <- bind_rows(tib, slice(tib, c(1, 1, 3)))
> tib2 %>% as.data.frame()
nama title seiyu
1 ライスシャワー ウマ娘 石見舞菜香
2 スーパークリーク ウマ娘 優木かな
3 メイショウドトウ ウマ娘 和多田美咲
4 フィー ライザのアトリエ2 和多田美咲
5 黒川あかね 推しの子 石見舞菜香
6 ライスシャワー ウマ娘 石見舞菜香
7 ライスシャワー ウマ娘 石見舞菜香
8 メイショウドトウ ウマ娘 和多田美咲
> tib2 %>% group_by(title, seiyu) %>% summarize(nn = n()) %>% as.data.frame()
`summarise()` has grouped output by 'title'. You can override using the `.groups` argument.
title seiyu nn
1 ウマ娘 優木かな 1
2 ウマ娘 和多田美咲 2
3 ウマ娘 石見舞菜香 3
4 ライザのアトリエ2 和多田美咲 1
5 推しの子 石見舞菜香 1
画面表示でtibbleの中身を任意の行数出力する
> library(tidyverse)
> nn <- 20
> n <- 1:nn
> s0 <- c("鈴木みのり", "近藤唯", "会沢紗弥")
> s <- sample(s0, nn, replace = TRUE)
> tib <- tibble(n, s)
> tib
# A tibble: 20 × 2
n s
<int> <chr>
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 鈴木みのり
> print(tib, n = 4)
# A tibble: 20 × 2
n s
<int> <chr>
1 1 鈴木みのり
2 2 近藤唯
3 3 近藤唯
4 4 会沢紗弥
# ℹ 16 more rows
# ℹ Use `print(n = ...)` to see more rows
> tib %>% print(n = 4)
# A tibble: 20 × 2
n s
<int> <chr>
1 1 鈴木みのり
2 2 近藤唯
3 3 近藤唯
4 4 会沢紗弥
# ℹ 16 more rows
# ℹ Use `print(n = ...)` to see more rows
連結
行方向にtibbleを連結する
bind_rows関数を使う。rbind関数と同様に列名を基準にして連結するため、列名の順は異なっていてもかまわない。なお、最後の例のとおり、rbind関数とは異なり列名が一致しない場合はNAを挿入して強制的に連結する。
> library(tidyverse)
> tib1 <- tibble(
+ no = c(40, 45),
+ name = c("ゴールドシチー", "スーパークリーク")
+ )
> tib2 <- tibble(
+ name = c("メイショウドトウ", "サクラチヨノオー"),
+ no = c(58, 69)
+ )
> tib1 %>% as.data.frame()
no name
1 40 ゴールドシチー
2 45 スーパークリーク
> tib2 %>% as.data.frame()
name no
1 メイショウドトウ 58
2 サクラチヨノオー 69
> bind_rows(tib1, tib2) %>% as.data.frame()
no name
1 40 ゴールドシチー
2 45 スーパークリーク
3 58 メイショウドトウ
4 69 サクラチヨノオー
> tib3 <- tibble(
+ no = c(58, 69),
+ seiyu = c("和多田美咲", "野口瑠璃子")
+ )
> tib3 %>% as.data.frame()
no seiyu
1 58 和多田美咲
2 69 野口瑠璃子
> bind_rows(tib1, tib3) %>% as.data.frame()
no name seiyu
1 40 ゴールドシチー <NA>
2 45 スーパークリーク <NA>
3 58 <NA> 和多田美咲
4 69 <NA> 野口瑠璃子
列方向にtibbleを連結する
bind_cols関数を使う。最後の例のとおり、行数が揃わない場合は連結できない。
> library(tidyverse)
> no <- c(40, 45, 58)
> name <- c("ゴールドシチー", "スーパークリーク", "メイショウドトウ")
> seiyu <- c("香坂さき", "優木かな", "和多田美咲")
> tib1 <- tibble(no, name)
> tib2 <- tibble(seiyu)
> tib1 %>% as.data.frame()
no name
1 40 ゴールドシチー
2 45 スーパークリーク
3 58 メイショウドトウ
> tib2 %>% as.data.frame()
seiyu
1 香坂さき
2 優木かな
3 和多田美咲
> bind_cols(tib1, tib2) %>% as.data.frame()
no name seiyu
1 40 ゴールドシチー 香坂さき
2 45 スーパークリーク 優木かな
3 58 メイショウドトウ 和多田美咲
> tib3 <- tibble(seiyu = c("鈴木みのり", "石見舞菜香"))
> tib3 %>% as.data.frame()
seiyu
1 鈴木みのり
2 石見舞菜香
> bind_cols(tib1, tib3)
Error in `bind_cols()`:
! Can't recycle `..1` (size 3) to match `..2` (size 2).
Run `rlang::last_trace()` to see where the error occurred.
結合
tibbleに別のtibbleで特定の列が一致する列を結合する
tidyverse(dplyr)パッケージのinner_join関数を使う。Aを基準としてBを結合する場合、inner_join関数ではBに指定の列の値がAにない場合は、Aのその行は出力から落とされる。落とされずにとりあえずAの行すべてを出力したい場合は、left_join関数を使う。指定の列を基準としてAにもBにも含まれる行を出力する場合はfull_join関数を使う。なお、簡潔な表示にするため、表示する際にはデータフレームに変換している。
> library(tidyverse)
> tbl <- read_csv("meibo.csv", show_col_types = FALSE, progress = FALSE)
> tbl2 <- tibble(no = c(1, 2, 4, 5), size = c("S", "M", "L", "LL"))
> as.data.frame(tbl)
no sei mei age weight
1 1 あいう えお 11 101.1
2 2 かきく けこ 22 202.2
3 3 さしす せそ 22 303.3
4 4 あいう けこ 33 404.4
> as.data.frame(tbl2)
no size
1 1 S
2 2 M
3 4 L
4 5 LL
> as.data.frame(tbl %>% inner_join(tbl2, by = "no"))
no sei mei age weight size
1 1 あいう えお 11 101.1 S
2 2 かきく けこ 22 202.2 M
3 4 あいう けこ 33 404.4 L
> as.data.frame(tbl %>% left_join(tbl2, by = "no"))
no sei mei age weight size
1 1 あいう えお 11 101.1 S
2 2 かきく けこ 22 202.2 M
3 3 さしす せそ 22 303.3 <NA>
4 4 あいう けこ 33 404.4 L
> as.data.frame(tbl %>% full_join(tbl2, by = "no"))
no sei mei age weight size
1 1 あいう えお 11 101.1 S
2 2 かきく けこ 22 202.2 M
3 3 さしす せそ 22 303.3 <NA>
4 4 あいう けこ 33 404.4 L
5 5 <NA> <NA> NA NA LL
指定の列の値を基準にして2つのtibbleを結合する
tidyverse(dplyr)パッケージのleft_join関数、right_join関数、inner_join関数、full_join関数を使う。基準とする列の指定にはjoin_by関数を使う。以下は、次の2つのtibbleを指定の列(以下の例ではcvとid)の値を基準にして結合した例。簡潔な表示にするため、表示はすべてデータフレームで行っている。
> library(tidyverse)
> chara %>% as.data.frame()
nama title no cv
1 ライスシャワー ウマ娘 30 miwami01
2 スーパークリーク ウマ娘 45 kyuki01
3 メイショウドトウ ウマ娘 58 mwatada01
4 ライザ ライザのアトリエ2 1 ynoguchi01
5 フィー ライザのアトリエ2 2 mwatada01
6 黒川あかね 推しの子 6 miwami01
> seiyu %>% as.data.frame()
id name
1 miwami01 石見舞菜香
2 kyuki01 優木かな
3 mwatada01 和多田美咲
4 machico01 Machico
left_join関数は、左側のtibbleの行はすべて採用され、右側のtibbleは指定の列が一致した行だけが結合される。一致の無かった左側の行の連結により作成される列にはNAが挿入される(以下の4行目)。
> chara %>% left_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 ライザ ライザのアトリエ2 1 ynoguchi01 <NA>
5 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
6 黒川あかね 推しの子 6 miwami01 石見舞菜香
right_join関数は、右側のtibbleの列はすべて採用され、左側のtibbleは指定の列が一致した行だけが結合される。一致の無かった右側の行の連結により作成される列にはNAが挿入される(以下の6行目)。
> chara %>% right_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
5 黒川あかね 推しの子 6 miwami01 石見舞菜香
6 <NA> <NA> NA machico01 Machico
inner_join関数は、指定の列の値が一致した組み合わせのみがすべて結合される。
> chara %>% inner_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
5 黒川あかね 推しの子 6 miwami01 石見舞菜香
full_join関数は、左側のtibbleの行はすべて採用され、右側のtibbleの行もすべて採用される。指定の列が一致したものは一致したもの同士で結合し、結合できない行の空いた列にはNAが挿入されて結合される(以下の4行目と7行目)。
> chara %>% full_join(seiyu, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 ライザ ライザのアトリエ2 1 ynoguchi01 <NA>
5 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
6 黒川あかね 推しの子 6 miwami01 石見舞菜香
7 <NA> <NA> NA machico01 Machico
二つのtibbleを一つに結合(左外部結合)する
左外部結合(左側のすべての行を必ず出力する結合)するには、left_join関数を使う。以下はあらかじめ用意した二つのtibbleを左外部結合した例。左側(tib1)の4行目は右側(tib2)に結合相手が見つからないため、列にNAを挿入して4行目に出力されていることがわかる。
> library(tidyverse)
> tib1 %>% as.data.frame()
nama title no cv
1 ライスシャワー ウマ娘 30 miwami01
2 スーパークリーク ウマ娘 45 kyuki01
3 メイショウドトウ ウマ娘 58 mwatada01
4 ライザ ライザのアトリエ2 1 ynoguchi01
5 フィー ライザのアトリエ2 2 mwatada01
6 黒川あかね 推しの子 6 miwami01
> tib2 %>% as.data.frame()
id name
1 miwami01 石見舞菜香
2 kyuki01 優木かな
3 mwatada01 和多田美咲
4 machico01 Machico
> tib1 %>% left_join(tib2, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 ライザ ライザのアトリエ2 1 ynoguchi01 <NA>
5 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
6 黒川あかね 推しの子 6 miwami01 石見舞菜香
二つのtibbleを一つに結合(右外部結合)する
右外部結合(右側のすべての行を必ず出力する結合)するには、right_join関数を使う。以下はあらかじめ用意した二つのtibbleを右外部結合した例。右側(tib2)の4行目は左側(tib1)に結合相手が見つからないため、列にNAを挿入して6行目に出力されていることがわかる。
> library(tidyverse)
> tib1 %>% as.data.frame()
nama title no cv
1 ライスシャワー ウマ娘 30 miwami01
2 スーパークリーク ウマ娘 45 kyuki01
3 メイショウドトウ ウマ娘 58 mwatada01
4 ライザ ライザのアトリエ2 1 ynoguchi01
5 フィー ライザのアトリエ2 2 mwatada01
6 黒川あかね 推しの子 6 miwami01
> tib2 %>% as.data.frame()
id name
1 miwami01 石見舞菜香
2 kyuki01 優木かな
3 mwatada01 和多田美咲
4 machico01 Machico
> tib1 %>% right_join(tib2, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
5 黒川あかね 推しの子 6 miwami01 石見舞菜香
6 <NA> <NA> NA machico01 Machico
二つのtibbleを一つに結合(完全外部結合)する
完全外部結合(左右すべての行を必ず出力する結合)するには、full_join関数を使う。以下はあらかじめ用意した二つのtibbleを完全外部結合した例。
> library(tidyverse)
> tib1 %>% as.data.frame()
nama title no cv
1 ライスシャワー ウマ娘 30 miwami01
2 スーパークリーク ウマ娘 45 kyuki01
3 メイショウドトウ ウマ娘 58 mwatada01
4 ライザ ライザのアトリエ2 1 ynoguchi01
5 フィー ライザのアトリエ2 2 mwatada01
6 黒川あかね 推しの子 6 miwami01
> tib2 %>% as.data.frame()
id name
1 miwami01 石見舞菜香
2 kyuki01 優木かな
3 mwatada01 和多田美咲
4 machico01 Machico
> tib1 %>% full_join(tib2, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 ライザ ライザのアトリエ2 1 ynoguchi01 <NA>
5 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
6 黒川あかね 推しの子 6 miwami01 石見舞菜香
7 <NA> <NA> NA machico01 Machico
二つのtibbleを一つに結合(内部結合)する
内部結合(結合すべき行がない行は出力しない結合)するには、inner_join関数を使う。以下はあらかじめ用意した二つのtibbleを内部結合した例。結合相手がない左側(tib1)の4行目と右側(tib2)の4行目は出力されていないことがわかる。
> library(tidyverse)
> tib1 %>% as.data.frame()
nama title no cv
1 ライスシャワー ウマ娘 30 miwami01
2 スーパークリーク ウマ娘 45 kyuki01
3 メイショウドトウ ウマ娘 58 mwatada01
4 ライザ ライザのアトリエ2 1 ynoguchi01
5 フィー ライザのアトリエ2 2 mwatada01
6 黒川あかね 推しの子 6 miwami01
> tib2 %>% as.data.frame()
id name
1 miwami01 石見舞菜香
2 kyuki01 優木かな
3 mwatada01 和多田美咲
4 machico01 Machico
> tib1 %>% full_join(tib2, by = join_by(cv == id)) %>% as.data.frame()
nama title no cv name
1 ライスシャワー ウマ娘 30 miwami01 石見舞菜香
2 スーパークリーク ウマ娘 45 kyuki01 優木かな
3 メイショウドトウ ウマ娘 58 mwatada01 和多田美咲
4 ライザ ライザのアトリエ2 1 ynoguchi01 <NA>
5 フィー ライザのアトリエ2 2 mwatada01 和多田美咲
6 黒川あかね 推しの子 6 miwami01 石見舞菜香
7 <NA> <NA> NA machico01 Machico
集計
tibbleで特定の列の値を基準にして集計を行う
例えば家計簿のように、日にちと金額が一対一で対応しているデータについて、毎日の入出金の流れを見たい場合など。
各情報の基準は日にちであり、同じ日にいくつも入金や出金が発生する日があり、この基準となる日付には重複がある。このようなデータを一覧で見るぶんにはよいが、毎日の入出金の流れはこれでは見ることはできない。この例では、日ごとに金額の集計を行いたい。この場合は、日にちごとの金額の和を計算してまとめたい。
このような場合は、group_by関数でtibble内部でグループ化を行い、それをsummarize関数で処理することで、集計後のtibbleに変換することができる。以下、実行例。表示を簡潔にするため、データフレームに変換して表示している。
> tib %>% as.data.frame()
date type value
1 2023-10-03 入金 200
2 2023-10-04 電気 4
3 2023-10-07 ガス 5
4 2023-10-07 電話 7
5 2023-10-09 水道 6
> tib %>% group_by(date) %>% as.data.frame()
date type value
1 2023-10-03 入金 200
2 2023-10-04 電気 4
3 2023-10-07 ガス 5
4 2023-10-07 電話 7
5 2023-10-09 水道 6
> tib %>% group_by(date) %>% summarize(value = sum(value)) %>% as.data.frame()
date value
1 2023-10-03 200
2 2023-10-04 4
3 2023-10-07 12
4 2023-10-09 6
group_by関数は内部でグループ化を行っているだけであり、2番目の実行例のとおりgroup_by関数だけでは集計が行われない(表示されない)ことに注意。
その他
tibbleの行に連番付け、順位付けを行う
連番付けにはrow_number関数、順位付けにはmin_rank関数かdense_rank関数を使う。
row_number関数は行に対して1から始まる連番を作成する。min_rank関数とdense_rank関数は順位付け関数であるが動作が異なり、min_rank関数は指定の列の値に同じ値があった場合は同位としてその次の順位を飛ばすが、dense_rank関数は同じ値があった場合は同位として次の順位は飛ばさない。最後の例のとおり、row_number関数は与えられたtibbleについて1行目から連番を割り当てるが、min_rank関数とdense_rank関数は指定された列の値に基づいて順位付けを行う。順位付けのデフォルトは昇順のため、これを降順にしたい場合は列を指定する際にdesc関数を使用する。
> library(tidyverse)
> tib <- tibble(n = c(20, 20, 30, 10, 40))
> tib %>% arrange(n) %>% mutate(row_number(), min_rank(n), dense_rank(n)) %>% as.data.frame()
n row_number() min_rank(n) dense_rank(n)
1 10 1 1 1
2 20 2 2 2
3 20 3 2 2
4 30 4 4 3
5 40 5 5 4
> tib %>% arrange(n) %>% mutate(row_number(), min_rank(desc(n)), dense_rank(desc(n))) %>% as.data.frame()
n row_number() min_rank(desc(n)) dense_rank(desc(n))
1 10 1 5 4
2 20 2 3 3
3 20 3 3 3
4 30 4 2 2
5 40 5 1 1
> tib %>% mutate(row_number(), min_rank(desc(n)), dense_rank(desc(n))) %>% as.data.frame()
n row_number() min_rank(desc(n)) dense_rank(desc(n))
1 20 1 3 3
2 20 2 3 3
3 30 3 2 2
4 10 4 5 4
5 40 5 1 1
テキストファイルの読み込み
テキストファイルを高速で読み込む
形式はともかく、とにかくテキストファイルを高速で読み込みたい場合は、readrパッケージのread_lines関数を使う。以下は、最初にファイルのサイズが80,000,000バイトのテキストファイルを作成し、それをRに標準で搭載されているscan関数とreadrパッケージのread_lines関数で3回ずつ読み込み、それに要した時間を計測した例。
作成したファイル(temp.txt)はWindowsのUTF-8環境で作成しており、1行78文字で改行コードはCR+LF、それが100万行あるテキストファイルのため、ファイルサイズは(78+2)*1,000,000=80,000,000バイトである。
> lns <- sprintf("%078.0f", floor(runif(10 ^ 6, 0, 10 ^ 78)))
> head(lns, 3)
[1] "214418413117527971264060246646220804826684668888086204426268668846486202246440"
[2] "923248178558424118646448222222446482266040066668404462646882848600280046042684"
[3] "022663331590592860430486024422482606408624828266462802622284262068424466884282"
> cat(lns, file = "temp.txt", sep = "\n")
> system.time(lns1 <- scan(file = "temp.txt", what = character(), sep = "\n", quiet = TRUE))
ユーザ システム 経過
4.74 0.11 4.95
> system.time(lns1 <- scan(file = "temp.txt", what = character(), sep = "\n", quiet = TRUE))
ユーザ システム 経過
4.64 0.16 4.81
> system.time(lns1 <- scan(file = "temp.txt", what = character(), sep = "\n", quiet = TRUE))
ユーザ システム 経過
4.56 0.14 4.70
> class(lns1)
[1] "character"
> length(lns1)
[1] 1000000
> head(lns1, 3)
[1] "214418413117527971264060246646220804826684668888086204426268668846486202246440"
[2] "923248178558424118646448222222446482266040066668404462646882848600280046042684"
[3] "022663331590592860430486024422482606408624828266462802622284262068424466884282"
> library(readr)
> system.time(lns2 <- read_lines(file = "temp.txt", progress = FALSE))
ユーザ システム 経過
1.07 0.24 0.71
> system.time(lns2 <- read_lines(file = "temp.txt", progress = FALSE))
ユーザ システム 経過
0.88 0.17 0.53
> system.time(lns2 <- read_lines(file = "temp.txt", progress = FALSE))
ユーザ システム 経過
1.04 0.06 0.53
> class(lns2)
[1] "character"
> length(lns2)
[1] 1000000
> head(lns2, 3)
[1] "214418413117527971264060246646220804826684668888086204426268668846486202246440"
[2] "923248178558424118646448222222446482266040066668404462646882848600280046042684"
[3] "022663331590592860430486024422482606408624828266462802622284262068424466884282"
単純な比較だがread_lines関数のほうが10倍弱速いことがわかる。read_lines関数で読み込んだものは、一行一要素の文字列型ベクトルになる。
巨大なCSVファイルを高速で読み込む
tribbleパッケージのread_csv関数を使用する。まずは巨大なCSVファイルを作成する。PowerShellのコマンドラインで以下を実行する。
PS > $s = "1,abc,2.3`r`n2,あい,4.5`r`n3,えおyz,NA`r`n"
PS > [Text.Encoding]::GetEncoding("utf-8").GetByteCount($s)
40
PS > $n = 1024 * 1024 * 4
PS > $file = (gl).Path + "\temp_utf8nb.csv"
PS > [IO.File]::WriteAllText($file, $s * $n)
PS > Get-ChildItem .\temp_utf8nb.csv
ディレクトリ: ○○○
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2023/08/20 22:27 167772160 temp_utf8nb.csv
PS > Get-Content .\temp_utf8nb.csv -TotalCount 5 -Encoding utf8
1,abc,2.3
2,あい,4.5
3,えおyz,NA
1,abc,2.3
2,あい,4.5
変数$sには大きさが40バイトの文字列(改行コード含む)が格納され、それを1024倍して40KiB(キビバイト)、さらに1024倍して40MiB(メビバイト)、最後に4倍して160MiBにしてCSVファイル(temp_utf8nb.csv)に出力している。これの160MiBのCSVファイルを使用する。なお、FileクラスのWriteAllTextメソッドを使用して文字コードをUTF-8(BOM無し)で出力していることに注意。改行コードは$sの中身のとおりにCR+LF。
Rで標準で使うことができるread.table関数を使ってみる。
> system.time(dtf <- read.table("temp_utf8nb.csv", sep = ",", fileEncoding = "UTF-8"))
ユーザ システム 経過
7.50 0.16 7.84
> system.time(dtf <- read.table("temp_utf8nb.csv", sep = ",", fileEncoding = "UTF-8"))
ユーザ システム 経過
7.10 0.14 7.88
> system.time(dtf <- read.table("temp_utf8nb.csv", sep = ",", fileEncoding = "UTF-8"))
ユーザ システム 経過
7.33 0.15 7.83
> nrow(dtf)
[1] 12582912
> head(dtf, 5)
V1 V2 V3
1 1 abc 2.3
2 2 あい 4.5
3 3 えおyz NA
4 1 abc 2.3
5 2 あい 4.5
キャッシュの影響を考慮して3回試している。この環境では読み込みに7.8秒程度要する。次にreadrパッケージのread_csv関数を使ってみる。
> library(readr)
> system.time(tbl <- read_csv("temp_utf8nb.csv", col_names = FALSE, progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.70 0.12 1.34
> system.time(tbl <- read_csv("temp_utf8nb.csv", col_names = FALSE, progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.42 0.19 1.31
> system.time(tbl <- read_csv("temp_utf8nb.csv", col_names = FALSE, progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.56 0.22 1.36
> nrow(tbl)
[1] 12582912
> head(as.data.frame(tbl), 5)
X1 X2 X3
1 1 abc 2.3
2 2 あい 4.5
3 3 えおyz NA
4 1 abc 2.3
5 2 あい 4.5
キャッシュの影響を考慮して3回試している。この環境では読み込みに1.4秒程度要する。read_csvはread.tableよりもファイルの読み込みが5倍以上早いことがわかる。なお、read_delim関数でも同じくらい早ことがわかる。
> system.time(tbl <- read_delim("temp_utf8nb.csv", col_names = FALSE, delim = ",", progress = FALSE, show_col_types = FALSE))
ユーザ システム 経過
7.14 0.08 1.25
原因は不明だが、このテスト環境(Windows版4.2.2)では、read.csv関数はfileEncodingオプションが指定どおり動作しない。そのため、上の例では代わりにread.table関数を使用している。
read_lines関数で様々な文字コードのテキストファイルを読み込む
localeオプションを使用する。はじめに、この動作確認のためのテキストファイルをPowerShellで作成する。それぞれ文字コードがシフトJISとUTF-8(BOM無し)のCSVファイルを作成している。
PS > $lines = "1,セナディア,鈴木みのり", "2,イレイナ,本渡楓"
PS > $odir = (gl).Path
PS > $lines | Out-File -Encoding default ($odir + "\sjis.csv")
PS > [IO.File]::WriteAllLines(($odir + "\utf8nb.csv"), $lines)
PS > Get-Content sjis.csv
1,セナディア,鈴木みのり
2,イレイナ,本渡楓
PS > Get-Content utf8nb.csv -Encoding utf8
1,セナディア,鈴木みのり
2,イレイナ,本渡楓
read_lines関数を使用する際に、localeオプションに文字コードを指定すればよい。以下の例のとおり、デフォルトではUTF-8で読み込もうとするため、UTF-8であれば明示的に指定しなくてもかまわない。
> library(tidyverse)
> read_lines("sjis.csv", progress = FALSE)
[1] "1,<83>Z<83>i<83>f<83>B<83>A,<97><e9><96><U+0602><U+0742><U+0302><e8>" "2,<83>C<83><8c><83>C<83>i,<96>{<93>n<95><96>"
> read_lines("sjis.csv", progress = FALSE, locale = locale(encoding = "SJIS"))
[1] "1,セナディア,鈴木みのり" "2,イレイナ,本渡楓"
> read_lines("utf8nb.csv", progress = FALSE)
[1] "1,セナディア,鈴木みのり" "2,イレイナ,本渡楓"
> read_lines("utf8nb.csv", progress = FALSE, locale = locale(encoding = "UTF-8"))
[1] "1,セナディア,鈴木みのり" "2,イレイナ,本渡楓"
テキストファイルへの書き込み
TSV形式でテキストファイルに高速で書き込む
readrパッケージのwrite_tsv関数を使う。以下は500万行からなるデータフレームをwrite.tableとwrite_tsv関数でそれぞれTSV形式のテキストファイルに3回ずつ出力し、それに要した時間を計測した例。write_tsv関数のほうが10倍以上速いことがわかる。
> library(readr)
> n <- 5 * 10 ^ 6
> no <- 1:n
> s <- c("大橋彩香", "石見舞菜香", "優木かな", "和多田美咲")
> name <- sample(s, n, replace = TRUE)
> shoe_size <- round(rnorm(n, 23.5, 1), 1)
> dtf <- data.frame(no, name, shoe_size)
> head(dtf, 6)
no name shoe_size
1 1 石見舞菜香 24.3
2 2 石見舞菜香 23.2
3 3 和多田美咲 23.6
4 4 大橋彩香 24.8
5 5 石見舞菜香 25.1
6 6 優木かな 24.7
> system.time(
+ write.table(dtf, "temp.tsv", sep = "\t", quote = FALSE, row.names = FALSE)
+ )
ユーザ システム 経過
9.86 0.06 12.78
> system.time(
+ write.table(dtf, "temp.tsv", sep = "\t", quote = FALSE, row.names = FALSE)
+ )
ユーザ システム 経過
9.43 0.14 12.94
> system.time(
+ write.table(dtf, "temp.tsv", sep = "\t", quote = FALSE, row.names = FALSE)
+ )
ユーザ システム 経過
9.55 0.09 13.06
> system.time(write_tsv(dtf, "temp.tsv", eol = "\r\n", progress = FALSE))
ユーザ システム 経過
0.60 0.05 0.16
> system.time(write_tsv(dtf, "temp.tsv", eol = "\r\n", progress = FALSE))
ユーザ システム 経過
0.62 0.10 0.16
> system.time(write_tsv(dtf, "temp.tsv", eol = "\r\n", progress = FALSE))
ユーザ システム 経過
0.92 0.07 0.84
その他
read_delim関数を使うと画面表示が乱れる(カーソルが飛ぶ)
readrパッケージのread_delim関数は、デフォルトでは、読み込み時に実際は表示されないものの経過を画面表示しようとするため、その影響で、使用後は画面表示が乱れ、カーソルがおかしなところに飛んでしまう。この画面表示の乱れが起きないようにするには、progressオプションにFALSEを指定する。
> library(readr)
> tbl <- read_delim("c:/windows/win.ini", delim = "\n", col_names = FALSE)
←カーソルがコマンドラインのプロンプトから離れた箇所に表示され、表示が乱れる。
一度Rを終了し、再起動して次のコマンドを実行する。
> library(readr)
> tbl <- read_delim("c:/windows/win.ini", delim = "\n", col_names = FALSE, progress = FALSE)
←カーソルがコマンドラインのプロンプトのすぐ右側に表示され、表示が乱れない。
以下を.RProfileに記述しておけば、R起動時に自動的に読み込み、デフォルトでそのような設定になる。
options(
readr.show_progress = FALSE
)
R起動後でも、以下のコマンドを実行すれば同じようにデフォルトでそのような設定になる。
> options(readr.show_progress = FALSE)
write_delim関数を使うと画面表示が乱れる(カーソルが飛ぶ)
readrパッケージのwrite_delim関数は、デフォルトでは出力の経過を画面表示しようとするため、その影響で、使用後は画面表示が乱れてカーソルがおかしなところに飛んでしまう。この画面表示の乱れが起きないようにするには、progressオプションにFALSEを指定する。
> library(tidyverse)
> tbl <- tibble(no = 1:3, name = c("ABC", "abc", "123"))
> write_delim(tbl, "temp.csv", delim = ",")
←カーソルがコマンドラインのプロンプトから離れた箇所に表示され、表示が乱れる。
一度Rを終了し、再起動して次のコマンドを実行する。
> library(tidyverse)
> tbl <- tibble(no = 1:3, name = c("ABC", "abc", "123"))
> write_delim(tbl, "temp.csv", delim = ",", progress = FALSE)
←カーソルがコマンドラインのプロンプトのすぐ右側に表示され、表示が乱れない。
以下を.RProfileに記述しておけば、R起動時に自動的に読み込み、デフォルトでそのような設定になる。
options(
readr.show_progress = FALSE
)
R起動後でも、以下のコマンドを実行すれば同じようにデフォルトでそのような設定になる。
> options(readr.show_progress = FALSE)
なお、これらはwrite_csv関数などでも同様である。
read_delim関数使用時の画面表示を抑制する
readrパッケージのread_delim関数は、デフォルトでは、読み込み時にいろいろ情報を表示する。これを一切表示させないようにするには、show_col_typesにFALSEを指定する。読み込みの経過を表示させないようにするため、あらかじめprogressにもFALSEを指定している。
> library(readr)
> tbl <- read_delim("c:/windows/win.ini", delim = "\n", col_names = FALSE, progress = FALSE)
Rows: 7 Columns: 1
── Column specification ─────────────────────────────────
Delimiter: "\001"
chr (1): X1
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
> tbl <- read_delim("c:/windows/win.ini", delim = "\n", col_names = FALSE, progress = FALSE, show_col_types = FALSE)
>
以下を「C:\Users\○○○\Documents\.RProfile」(○○○はアカウント名)に記述しておけば、R起動時に自動的に読み込み、デフォルトでそのような設定になる。
options(
readr.show_progress = FALSE,
readr.show_col_types = FALSE
)
R起動後でも、以下のコマンドを実行すれば同じようにデフォルトでそのような設定になる。
> options(readr.show_progress = FALSE, readr.show_col_types = FALSE)
試してみる。
> library(readr)
> tbl <- read_delim("c:/windows/win.ini", delim = "\n", col_names = FALSE)
>
read_xlsx関数を使うと画面表示が乱れる(カーソルが飛ぶ)
readxlパッケージのread_xlsx関数は、デフォルトでは、読み込み時に実際は表示されないものの経過を画面表示しようとするため、その影響で、使用後は画面表示が乱れ、カーソルがおかしなところに飛んでしまう。この画面表示の乱れが起きないようにするには、progressオプションにFALSEを指定する。
> library(readxl)
> tib <- read_xlsx("sample.xlsx")
←カーソルがコマンドラインのプロンプトから離れた箇所に表示され、表示が乱れる。
一度Rを終了し、再起動して次のコマンドを実行する。
> library(readxl)
> tib <- read_xlsx("sample.xlsx", progress = FALSE)
←カーソルがコマンドラインのプロンプトのすぐ右側に表示され、表示が乱れない。
以下を.RProfileに記述しておけば、R起動時に自動的に読み込み、デフォルトでそのような設定になる。
options(
readxl.show_progress = FALSE
)
R起動後でも、以下のコマンドを実行すれば同じようにデフォルトでそのような設定になる。
options(readxl.show_progress = FALSE)
write_csv関数で出力される日付時刻型ベクトルについて
日付時刻型ベクトルを出力すると、UTCに変換されて出力されることに注意。なお、日付型ベクトルは当然この影響を受けない。
現在の環境の日時を表す文字列で出力したければ、文字列に変換する必要がある。
> library(tidyverse)
> options(readr.show_progress = FALSE, readr.show_col_types = FALSE)
> print(Sys.timezone())
[1] "Asia/Tokyo"
> dttm <- ymd_hms("2001-02-03 04:05:06")
> dat <- ymd("2010-11-12")
> print(dttm)
[1] "2001-02-03 04:05:06 UTC"
> print(dat)
[1] "2010-11-12"
> dtf <- data.frame(dttm, dat)
> write_csv(dtf, file = "temp.csv")
> cat(read_file("temp.csv"))
dttm,dat
2001-02-03T04:05:06Z,2010-11-12
> dttm <- ymd_hms("2001-02-03 04:05:06", tz = Sys.timezone())
> print(dttm)
[1] "2001-02-03 04:05:06 JST"
> dtf <- data.frame(dttm)
> write_csv(dtf, file = "temp.csv")
> cat(read_file("temp.csv"))
dttm
2001-02-02T19:05:06Z
> s <- format(dttm, "%Y-%m-%dT%H:%M:%S")
> print(s)
[1] "2001-02-03T04:05:06"
> dtf <- data.frame(dttm = s)
> write_csv(dtf, file = "temp.csv")
> cat(read_file("temp.csv"))
dttm
2001-02-03T04:05:06
> s = format(dttm, "%Y-%m-%dT%H:%M:%S%z")
> print(s)
[1] "2001-02-03T04:05:06+0900"
> dtf <- data.frame(dttm = s)
> write_csv(dtf, file = "temp.csv")
> cat(read_file("temp.csv"))
dttm
2001-02-03T04:05:06+0900
read_csv関数で読み込まれる日付時刻型ベクトルについて
CSVファイルにタイムゾーンも明記されている場合は、そのタイムゾーンの日付時刻として読み取るが、ベクトルにはUTCに変換して保存される。
タイムゾーンが明記されていない日付時刻は強制的にUTCであるとして読み込み、保存されてしまう。読み込み後にJSTにする場合は、force_tz関数でタイムゾーンだけをJSTに変える必要がある。
> library(tidyverse)
> options(readr.show_progress = FALSE, readr.show_col_types = FALSE)
> Sys.timezone()
[1] "Asia/Tokyo"
> s <- "2001-02-03T04:05:06+09:00"
> dtf <- data.frame(dttm = s)
> write_csv(dtf, file = "temp.csv")
> cat(read_file("temp.csv"))
dttm
2001-02-03T04:05:06+09:00
> tib <- read_csv("temp.csv")
> print(tib$dttm)
[1] "2001-02-02 19:05:06 UTC"
> s <- "2001-02-03T04:05:06"
> dtf <- data.frame(dttm = s)
> write_csv(dtf, file = "temp.csv")
> cat(read_file("temp.csv"))
dttm
2001-02-03T04:05:06
> tib <- read_csv("temp.csv")
> print(tib$dttm)
[1] "2001-02-03 04:05:06 UTC"
> tib <- tib |> mutate(dttm = force_tz(dttm, tzone = Sys.timezone()))
> print(tib$dttm)
[1] "2001-02-03 04:05:06 JST"