[1, 58, 10] などの文字列の列を、separate from tidyr を使用して列に分割したいと思います。私の問題は、列が短い場合があることです(決して長くはありません)。同じデータ フレームに、この問題が発生した列が多数あります。
パッケージの読み込み
require(tidyr)
require(dplyr)
require(stringr)
データ
ここでは、実際のデータからのサンプルを使用してデータ フレームを作成します。「ベクトル」の長さは、col1 では 10、col2 では 9 または 10 です。他の列があることを示すためだけに時間列があります。
df <- data.frame(
time = as.POSIXct(1:5, origin=Sys.time()),
col1 = c("[0,355,0,0,0,1227,0,0,382059,116]", "[0,31,0,0,0,5,0,0,925,1]", "[0,1,0,0,0,471,0,0,130339,3946]", "[0,0,0,0,0,223,0,0,37666,12]", "[0,19,0,0,0,667,0,0,336956,53]"),
col2 = c("[0,355,0,0,0,1227,0,0,382059,116]", "[0,355,0,0,0,1227,0,0,382059,116]", "[0,0,0,0,0,223,0,0,37666,12]", "[0,19,0,0,0,667,0,0,336956]","[0,355,0,0,0,1227,0,0,382059,116]")
)
どうなりたいか
すべての「ベクトル」が同じ長さの最初の列では、separate() を使用して必要なものを取得できます。
a1 <- df %>%
mutate(col1 = str_sub(col1,2,-2)) %>%
separate(col1, paste("col1",1:10,sep="."),",")
# Making sure the numbers are numeric
a1 <- as.data.frame(sapply(a1, as.numeric)) %>%
mutate(time = as.POSIXct(time, origin="1970-01-01")) %>% select(-col2)
これにより、
> a1
time col1.1 col1.2 col1.3 col1.4 col1.5 col1.6 col1.7 col1.8
1 2014-11-07 12:21:45 0 355 0 0 0 1227 0 0
2 2014-11-07 12:21:46 0 31 0 0 0 5 0 0
3 2014-11-07 12:21:47 0 1 0 0 0 471 0 0
4 2014-11-07 12:21:48 0 0 0 0 0 223 0 0
5 2014-11-07 12:21:49 0 19 0 0 0 667 0 0
col1.9 col1.10
1 382059 116
2 925 1
3 130339 3946
4 37666 12
5 336956 53
これは、要素を複数の列に分割できない col2 では機能しません
回避策
# Does not work
#b1 <- df %>%
# mutate(col2 = str_sub(col1,2,-2)) %>%
# separate(col2, paste("col2",1:10,sep="."),",")
b2 <- sapply(as.data.frame(str_split_fixed(str_sub(df$col2,2,-2),',',n=10), stringsAsFactors=F), as.numeric)
colnames(b2) <- paste("col2",1:10,sep=".")
b2 <- as.data.frame(cbind(time=df$time, b2)) %>%
mutate(time = as.POSIXct(time, origin="1970-01-01"))
その結果、
> b2
time col2.1 col2.2 col2.3 col2.4 col2.5 col2.6 col2.7 col2.8
1 2014-11-07 12:21:45 0 355 0 0 0 1227 0 0
2 2014-11-07 12:21:46 0 355 0 0 0 1227 0 0
3 2014-11-07 12:21:47 0 0 0 0 0 223 0 0
4 2014-11-07 12:21:48 0 19 0 0 0 667 0 0
5 2014-11-07 12:21:49 0 355 0 0 0 1227 0 0
col2.9 col2.10
1 382059 116
2 382059 116
3 37666 12
4 336956 NA
5 382059 116
ベクトルが短い場合、最後の要素は NA になるため、これは正しいです。
質問
回避策の代わりに別の (または他の単純な関数) を使用する方法はありますか? これを col1 と col2 に同時に適用する方法はありますか (たとえば、col で始まる列を選択することによって)?
ありがとう!