いろいろ倉庫

KNIME、EXCEL、R、Pythonなどの備忘録

【R】data.frameを読み込んだりくっつけたりしたい

・お題:data.frameの扱いをまだまだ覚えられないので、メモしておく。

 

・データは適当にcsvで用意した。

・とりあえず、tidyverseを読み込む。

> library(tidyverse)

csvを読み込む。

> df0<-read.csv("20230416_0.csv")
> df0

・これでも良いといえば良いけれど、少し弄る。

> df0<-read.csv("20230416_0.csv",
+               stringsAsFactors = FALSE,
+               sep = ",",
+               na.strings = "")
> df0

・IDを行名にする。

> rownames(df0) <- df0$ID
> df0

・ID列を消す。

> df0$ID <- NULL
> df0

・Scoreが文字列として読み込まれているので、数字にする。

> df0$Score <- as.numeric(df0$Score)
Warning message:
NAs introduced by coercion 
> df0

> df0 %>% str()
'data.frame':    6 obs. of  2 variables:
 $ Name : chr  "tanaka" "yamada" NA "sato" ...
 $ Score: num  1 2 3 NA NA 6

・ちなみに、dfを纏めて数値にしたければ、df <- as.data.frame(sapply(df, as.numeric))みたいな書き方もOK。今回はNameが数値でないので、やらない。

・もうひとつdata.frameを読み込む。

> df1<-read.csv("20230416_1.csv",
+               stringsAsFactors = FALSE,
+               sep = ",",
+               na.strings = "",
+               row.names = 1#行名になる列が分かっているならこれでOK
+               )
> df1$Score <- as.numeric(df1$Score)
Warning message:
NAs introduced by coercion 

> df1

・df1はdf0と列の順番が少し違う。しかも、df1にだけAgeがある。

・df0にdf1を縦にくっつける。
> df01<-bind_rows(df0,df1)
> df01

・なんだか良い感じにくっつけてくれた。

・もう一つ、データを読み込む。

> df2<-read.csv("20230416_2.csv",
+               stringsAsFactors = FALSE,
+               sep = ",",
+               na.strings = "",
+               row.names = 1
+               )
> df2

・df2は新たな列だけのデータフレームらしく、しかも行名がかなり歯抜けになっている。

・df01にdf2をくっつけるのに、bind_colsを使うとエラーが返ってくる。

> bind_cols(df01,df2)

Error in `bind_cols()`:
! Can't recycle `..1` (size 12) to match `..2` (size 6).
Run `rlang::last_trace()` to see where the error occurred.

・そこで、行名でくっつけるために、merge関数を使ってみるが、innner_joinっぽくなってうまくいかない。

> merge(df01, df2, by=0)

・なお、かくいうdplyrのjoinシリーズ(innner, outer, left, right)はbyに0を指定してもうまくいかない。

> inner_join(df01, df2, by=0)
Error in `inner_join()`:
! `by` must be a (named) character vector,   list, `join_by()` result, or NULL, not the number
  0.
Run `rlang::last_trace()` to see where the error occurred.

・そこで、無理やりやってみた。rownamesを列として作り直してくっつけてから消す。

> df012<-full_join(df01 %>% mutate(., ID = rownames(.)),
+                  df2 %>% mutate(., ID = rownames(.)),
+                  by="ID")
> df012

> rownames(df012)<-df012$ID
> df012 <- df012 %>% select(., -"ID")#selectにマイナスをつけると列を消せる
> df012

・一応できたが、センスがなさ過ぎて悶絶している。。

・merge関数のオプションでできるんじゃないかと思って調べてみると、確かにinnner_join以外のjoinをmergeで実行することもできるらしい。

stackoverflow.com

> merge(df01,
+       df2,
+       by = 0,
+       all = TRUE)

・しかしながら、Row.namesという列ができてしまっており、問題が解決していない。。もっと探せば何とかなりそうな気もする。。

 

 

おわり。