[英]Select from Multiple Columns - R
我有两组数据框。 一种是字符串的组合,其中有两列,食物的类型不同:
#df.combination
[,1] [,2]
[1,] "Apple" "Orange"
[2,] "Apple" "Pear"
[3,] "Apple" "Avocado"
[4,] "Orange" "Pear"
[5,] "Orange" "Avocado"
[6,] "Pear" "Avocado"
另一个是大型的“主要”数据框,其中包含三列食物(“ id”,“日期”,“ food1”,“ food2”,“ food3”),其中包含以下一些组合:
#df.main
[,1] [,2] [,3] [,4] [,5]
[1,] "1234" "3/29" "Sala" "Pear" "Avocado"
[2,] "1235" "3/30" "Apple" "Pear" "Meat"
[3,] "1236" "4/1" "Orange" "Juice" "Apple"
[4,] "1237" "4/2" "Pear" "Avocado""Turkey"
如果我想编写一个脚本来搜索df.main并从df.combination [1,]中选择包含所有元素的行(因此是“ Apple”和“ Orange”),我该怎么做? 食物不必乱序。 该行只需要容纳食物。 (即df.main [3,] )。
这是我想看到的示例输出。 如果我在df.main中搜索“ Orange”和“ Apple”(所以df.combination [1,] ),我想查看df.main [2,]行的ID。
#search df.main for row containing df.combination[1,]
#output:
#1236
谢谢! 任何帮助真的很感激。
你可以试试
f1 <- function(dat1, dat2, rowindex){
Indx <- apply(dat1[,grep('food', colnames(dat1))], 1,
function(x) all(unlist(dat2[rowindex,]) %in% x))
dat1[Indx,1]
}
f1(df.main, df.combination,1)
#[1] 1236
f1(df.main, df.combination,2)
#[1] 1235
f1(df.main, df.combination,3)
#integer(0)
df.main <- structure(list(id = 1234:1237, date = c("3/29", "3/30",
"4/1",
"4/2"), food1 = c("Sala", "Apple", "Orange", "Pear"),
food2 = c("Pear",
"Pear", "Juice", "Avocado"), food3 = c("Avocado", "Meat", "Apple",
"Turkey")), .Names = c("id", "date", "food1", "food2",
"food3"), class = "data.frame", row.names = c(NA, -4L))
df.combination <- structure(list(V1 = c("Apple", "Apple", "Apple",
"Orange", "Orange",
"Pear"), V2 = c("Orange", "Pear", "Avocado", "Pear", "Avocado",
"Avocado")), .Names = c("V1", "V2"), class = "data.frame",
row.names = c(NA, -6L))
为此,您可以编写一个扩展match函数的函数,以对包含某个向量的所有值的记录进行过滤,如下所示:
match_filter <- function(df, match_to) {
apply(df,
1,
function(row) {
!any(is.na(match(match_to, row)))
})
}
因此,功能match_filter
有2个参数:第一个是df
,在这种情况下将是您的df.main
数据集(或其子集-如我们所见)。 第二个是match_to
,它是我们要匹配的向量,或者我们希望将其所有值都包含在df
每个记录中。
该函数易于理解,但是,查看其某些组件很有用。 在这种情况下, match
函数的作用是针对match_to
向量中的每个值,返回其row
向量中的索引(在df
为一行)。 如果row
找不到该值,则返回NA
。 这是在您提供的数据集的第二行上运行匹配的示例:
> match(df.combination[1,], df.main[2,])
[1] 3 NA
现在,为了使记录row
这种情况下能够满足我们的要求,则match
函数返回的向量不应具有任何NA
值。 这就是为什么我们用!any(is.na())
包装match(match_to, row)
函数的原因。 因此,如果match
的返回值中有任何NA
,那么我们要丢弃该记录。
我们将所有这些包装在apply
函数中的原因是因为我们要在df
每一行上运行内部函数( function(row){...}
),这就是apply
函数的用途。
这是在数据集上使用上面定义的函数的示例:
> df.main[ match_filter(df.main[,3:5], df.combination[1,]),]
id date food1 food2 food3
3 1236 4/1 Orange Juice Apple
> subset(df.main, match_filter(df.main[,3:5], df.combination[1,]))
id date food1 food2 food3
3 1236 4/1 Orange Juice Apple
如您所见,由于在这种情况下您对df.main
数据帧中的3:5
列感兴趣,因此我们只将它们传递给match_filter
函数。
更新:
如果您想使用可以采用任意数量组合的函数,那么我们需要更新match_filter
来容纳它。 更新非常简单,并且遵循我们之前看到的相同逻辑:
match_filter <- function(df, match_to) {
apply(df,
1,
function(row1) {
any(apply(match_to,
1,
function(row2) {
!any(is.na(match(row2, row1)))
}))
})
}
现在match_filter
函数是一个更通用的函数,可以采用任意数量的组合,并检查row1
是否具有这些组合中的任何组合。 在这种情况下, match_to
可以是一个数据帧,对应于df.combination
。 以下是使用新功能的一些示例:
首先,出于说明目的,我添加了此假设记录:
df.main[5,] <- c("1238", "4/3", "Apple", "Avocado", "Orange" )
以下是该函数的用法示例:
# Example showing how the function
# works with only the first row of df.combination
> df.main[ match_filter(df.main[,3:5], df.combination[1,]),]
id date food1 food2 food3
3 1236 4/1 Orange Juice Apple
5 1238 4/3 Apple Avocado Orange
# The first 2 rows of df.combination
> df.main[ match_filter(df.main[,3:5], df.combination[1:2,]),]
id date food1 food2 food3
2 1235 3/30 Apple Pear Meat
3 1236 4/1 Orange Juice Apple
5 1238 4/3 Apple Avocado Orange
# All the rows in the df.combination dataframe
> df.main[ match_filter(df.main[,3:5], df.combination),]
id date food1 food2 food3
1 1234 3/29 Sala Pear Avocado
2 1235 3/30 Apple Pear Meat
3 1236 4/1 Orange Juice Apple
4 1237 4/2 Pear Avocado Turkey
5 1238 4/3 Apple Avocado Orange
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.