複数の列値に基づいて複数のデータフレームを取得するデータフレームをサブセット化しようとしています。これが私の例です
>df
v1 v2 v3 v4 v5
A Z 1 10 12
D Y 10 12 8
E X 2 12 15
A Z 1 10 12
E X 2 14 16
予想される出力は、このデータフレームを列v1
およびv2
に基づいて複数のデータフレームに分割しているようなものです。
>df1
v3 v4 v5
1 10 12
1 10 12
>df2
v3 v4 v5
10 12 8
>df3
v3 v4 v5
2 12 15
2 14 16
現在動作しているコードを記述しましたが、それが最善の方法だとは思いません。それを行うにはもっと良い方法があるはずです。 tab
が初期データを持つdata.frameであると仮定します。これが私のコードです:
v1Factors<-levels(factor(tab$v1))
v2Factors<-levels(factor(tab$v2))
for(i in 1:length(v1Factors)){
for(j in 1:length(v2Factors)){
subsetTab<-subset(tab, v1==v1Factors[i] & v2==v2Factors[j], select=c("v3", "v4", "v5"))
print(subsetTab)
}
}
誰かが上記を行うためのより良い方法を提案できますか?
split
を探しています
_split(df, with(df, interaction(v1,v2)), drop = TRUE)
$E.X
v1 v2 v3 v4 v5
3 E X 2 12 15
5 E X 2 14 16
$D.Y
v1 v2 v3 v4 v5
2 D Y 10 12 8
$A.Z
v1 v2 v3 v4 v5
1 A Z 1 10 12
_
コメントで述べたように
次のいずれでも機能します
_library(microbenchmark)
microbenchmark(
split(df, list(df$v1,df$v2), drop = TRUE),
split(df, interaction(df$v1,df$v2), drop = TRUE),
split(df, with(df, interaction(v1,v2)), drop = TRUE))
Unit: microseconds
expr min lq median uq max neval
split(df, list(df$v1, df$v2), drop = TRUE) 1119.845 1129.3750 1145.8815 1182.119 3910.249 100
split(df, interaction(df$v1, df$v2), drop = TRUE) 893.749 900.5720 909.8035 936.414 3617.038 100
split(df, with(df, interaction(v1, v2)), drop = TRUE) 895.150 902.5705 909.8505 927.128 1399.284 100
_
interaction
が少し速いようです(おそらくf = list(...)
が関数内のインタラクションに変換されているためです)
編集する
サブセットdata.framesのみを使用する場合は、コーディングを容易にするためにdata.tableを使用することをお勧めします
_library(data.table)
dt <- data.table(df)
dt[, plot(v4, v5), by = list(v1, v2)]
_
tidyr
からのnest()
もあるようになりました。
library(tidyr)
nestdf <- df %>% nest(v3:v5)
nestdf$data
> nestdf$data
[[1]]
# A tibble: 2 × 3
v3 v4 v5
<int> <int> <int>
1 1 10 12
2 1 10 12
[[2]]
# A tibble: 1 × 3
v3 v4 v5
<int> <int> <int>
1 10 12 8
[[3]]
# A tibble: 2 × 3
v3 v4 v5
<int> <int> <int>
1 2 12 15
2 2 14 16
nestdf$data[1]
などを使用して、個々のティブルにアクセスします。