Reputation: 3461
I have two data.frames:
df.1 <- data.frame(A=runif(10), B=runif(10), C=runif(10), D=runif(10))
df.2 <- data.frame(Var=factor(c("A", "B", "C", "D")), Info=c("X1", "X2", "X1", "X2"))
In df.1
, i want to select all columns which are associated with one factor level in df.2$Info
i can only do this in a very clumsy way by merging the two data.frames first, then subsetting, then rearraging the desired output:
tmp <- as.data.frame(t(df.1))
tmp$Var=row.names(tmp)
tmp.m <- merge(tmp, df.2, by="Var")
df.X1 <- tmp.m[tmp.m$Info == "X1", ]
df.X1$Info <- factor(df.X1$Info) # drop unused factor levels
desired.output <- as.data.frame(t(df.X1))
names(desired.output) <- lapply(desired.output[1, ], as.character)
desired.output <- desired.output[-c(1,11),]
My question is if there is a better, faster and less complicated way (i am sure there is!). Thank you.
Upvotes: 1
Views: 170
Reputation: 1702
A tidyverse
solution, maybe not quite as elegant as the others, but could open up some other possibilities:
library(tidyverse)
df.2sub <- df.2 %>%
filter(Info == "X1")
df.1sub <- df.1 %>%
select_if(colnames(.) %in% df.2sub$Var)
df.1sub
A C
1 0.99561926 0.6661509
2 0.68340388 0.5952997
3 0.21700589 0.6677539
4 0.07276628 0.2027971
5 0.70201107 0.4015561
6 0.86886930 0.7653709
7 0.71247007 0.1007955
8 0.96024317 0.7130610
9 0.04268316 0.9754990
10 0.67787175 0.8897161
EDIT:
There's a more parsimonious way with tidyverse
:
df.1sub <- df.1 %>%
select_if(colnames(.) %in% filter(df.2, Info == "X1")[["Var"]])
Upvotes: 1
Reputation: 887118
We can also loop through the unique
elements in 'Info' column, compare with the 'Info', extract the 'Var' elements and subset
lapply(unique(df.2$Info), function(nm) df.1[df.2$Var[df.2$Info == nm]])
Upvotes: 1
Reputation: 1019
df.1[,unique(df.2$Var[which(df.2$Info=="X1")])]
A C
1 0.8924861 0.7149490854
2 0.5711894 0.7200819517
3 0.7049629 0.0004052017
4 0.9188677 0.5007302717
5 0.3440664 0.9138259818
6 0.8657903 0.2724015017
7 0.7631228 0.5686033906
8 0.8388003 0.7377064163
9 0.0796059 0.6196693045
10 0.5029824 0.8717568610
Upvotes: 1
Reputation: 51592
You can split and subset, i.e.
lapply(split(df.2$Var, df.2$Info), function(i) df.1[i])
which gives,
$X1
A C
1 0.4666410 0.24030906
2 0.3246221 0.55153654
3 0.2042521 0.75376685
4 0.1130009 0.03761851
5 0.9979631 0.77633112
6 0.3611264 0.61717196
7 0.1535525 0.89337225
8 0.7068574 0.92468517
9 0.6951691 0.33549641
10 0.1637878 0.70826630
$X2
B D
1 0.06560149 0.24576981
2 0.23798129 0.53494840
3 0.62587837 0.08097668
4 0.38462826 0.98415256
5 0.94772413 0.85647140
6 0.90655926 0.97475473
7 0.48175364 0.24743947
8 0.65016599 0.75966646
9 0.19430794 0.82114764
10 0.97282206 0.19113057
Upvotes: 1