从多列中选择 - R.

时间:2015-03-29 16:35:34

标签: r

我有两组数据帧。一种是字符串的组合,其中有两列,具有不同类型的食物:

#df.combination

      [,1]     [,2] 
[1,] "Apple" "Orange"         
[2,] "Apple" "Pear"         
[3,] "Apple" "Avocado" 
[4,] "Orange" "Pear"   
[5,] "Orange" "Avocado"
[6,] "Pear" "Avocado"

另一个是主要的"主要"数据框包含三列食物(" id"" date"" 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"和#34; Orange"),我怎么能这样做?食物不必是任何顺序。这排只需要包含食物。 (即 df.main [3,] )。

以下是我希望看到的示例输出。如果我搜索" Orange"和#34; Apple" ( df.main 中的 df.combination [1,] ),我希望看到行 df.main [2,]的ID

#search df.main for row containing df.combination[1,]
#output:
#1236

谢谢!任何帮助真的很感激。

2 个答案:

答案 0 :(得分:1)

你可以尝试

 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))

答案 1 :(得分:0)

为此,您可以编写一个扩展匹配函数的函数来过滤包含特定向量的所有值的记录,如下所示:

match_filter <- function(df, match_to) { 
    apply(df, 
          1, 
          function(row) {
              !any(is.na(match(match_to, row)))
          })
}

因此,函数match_filter有两个参数:第一个是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个值。这就是我们将match(match_to, row)函数与!any(is.na())包装起来的原因。因此,如果NA的返回值中有match个,那么我们要丢弃该记录。

我们在apply函数中包含所有这些内容的原因是因为我们希望在function(row){...}的每一行上运行内部函数(df)并且这样做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

正如您所看到的,因为在这种情况下,您对3:5数据框中的df.main列感兴趣,我们只需将它们传递给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