基于来自两个单独数据帧的值对列进行子集化的问题

时间:2016-08-30 13:49:36

标签: r dataframe dplyr mapply

我正在使用从空间网格系统获得的数据,例如划分为等间距正方形(例如250平方米的单元格)的城市。每个单元格都拥有一个唯一的列和行号,以及有关该250平方米平方所包含区域的相应数字信息(即整个城市中每个单元的温度)。在整个网格部分(或示例城市)中,我有各种研究站点,我知道它们的位置(即每个站点位于哪个单元行和列中)。我有一个数据框,其中包含有关城市内所有单元格的信息,但我希望将其子集化为仅包含我的研究网站所在单元格的信息。我之前就此问题提出了一个问题Matching information from different dataframes and filtering out redundant columns'。这是一些示例代码:

###Dataframe showing cell values for my own study sites
Site <- as.data.frame(c("Site.A","Site.B","Site.C"))
Row <- as.data.frame(c(1,2,3))
Column <- as.data.frame(c(5,4,3))
df1 <- cbind(Site,Row, Column)
colnames(df1) <- c("Site","Row","Column")

###Dataframe showing information from ALL cells
eg1 <- rbind(c(1,2,3,4,5),c(5,4,3,2,1)) ##Cell rows and columns
eg2 <- as.data.frame(matrix(sample(0:50, 15*10, replace=TRUE), ncol=5)) ##Numerical information
df2 <- rbind(eg1,eg2)
rownames(df2)[1:2] <- c("Row","Column")

由此,我使用了之前问题的答案,这些答案对于示例数据非常有效。

output <- df2[, (df2['Row', ] %in% df1$Row) & (df2['Column', ] %in% df1$Column)]
names(output) <- df1$Site[mapply(function(r, c){which(r == df1$Row & c == df1$Column)}, output[1,], output[2,])]

但是,我无法将此应用于我自己的数据,也无法找出原因。

编辑:最初,我认为命名列存在问题(即&#39;名称&#39;功能)。但似乎“输出”可能会出现问题。代码行,其中df2中包含的列不应该是(即输出包含来自df2的列,其具有未在df1中指定的列和行号)。

我也尝试过:

output <- df2[, (df2['Row', ] == df1$Row) & (df2['Column', ] == df1$Column)]

但是当使用我自己的(看似可比较的)数据时,我无法从&#39; df1&#39;中指定的所有单元格获取信息。等效(虽然在上面的示例数据中再次正常工作)。如果我单独为每个研究地点进行研究,我可以获得自己的数据。

SiteA <- df2[, which(df2['Row', ] == 1) & (df2['Column', ] == 5)]
SiteB <- df2[, which(df2['Row', ] == 2) & (df2['Column', ] == 4)]
SiteC <- df2[, which(df2['Row', ] == 3) & (df2['Column', ] == 3)]

但我有1000个网站,并希望有一个更简洁的方式。我确信我保持了相同的结构,双重检查拼写和变量名称。是否有人能够揭露我可能做错的潜在事情?或者没有这种替代方法?

抱歉没有提供实际问题的示例代码(我希望我能够确定具体问题是什么,但在此之前,原始示例是我能做的最好的)!谢谢。

1 个答案:

答案 0 :(得分:1)

我能看到的唯一明显问题是mapply没有包裹unlistmapply会返回一个list,这不是您之后用于子集目的的内容。所以,试试:

output <- df2[, (df2['Row', ] %in% df1$Row) & (df2['Column', ] %in% df1$Column)]
names(output) <- df1$Site[unlist(mapply(function(r, c){which(r == df1$Row & c == df1$Column)}, output[1,], output[2,]))]

编辑:

如果目标是抓取前两行与df1中给定行的第二和第三个元素匹配的列,则可以尝试以下操作:

output_df <- Filter(function(x) !all(is.na(x)), data.frame(do.call(cbind,apply(df2, 2, function(x) {
  ##Create a condition vector for an if-statement or for subsetting
  condition <- paste0(x[1:2], collapse = "") == apply(df1[,c('Row','Column')], 1, function(y) {
    paste0(y,collapse = "")
  })
  ##Return a column if it meets the condition (first 2 rows are matched in df1)
  if(sum(condition) != 0) {
    tempdf <- data.frame(x)
    names(tempdf) <- df1[condition,]$Site[1]
    tempdf
  } else {
    ##If they are not matched, then return an empty column
    data.frame(rep(NA,nrow(df2)))
  }
}))))

这是一段相当简洁的代码,所以我希望以下解释有助于澄清一些事情:

这基本上遍历df2中的每一列(apply(df2, 2, FUN)),并检查df1中每行的第2和第3个元素是否可以找到它的前2行。如果满足条件,则它以data.frame格式返回该列,其列名为Site中匹配行中df1的值;否则返回一个空列(包含NA&#39; s)。然后将这些列与do.callcbind绑定在一起,然后强制转换为data.frame。最后,我们使用Filter函数删除值为NA的列。

所有这些都应该提供以下内容:

Site.A Site.B Site.C
  1      2      3    
  5      4      3    
 40     42     33    
 13     47     25    
 23      0     34    
  2     41     17    
 10     29     38    
 43     27      8    
 31      1     25    
 31     40     31    
 34     12     43    
 43     30     46    
 46     49     25    
 45      7     17    
  2     13     38    
 28     12     12    
 16     19     15    
 39     28     30    
 41     24     30    
 10     20     42    
 11      4      8    
 33     40     41    
 34     26     48    
  2     29     13    
 38      0     27    
 38     34     13    
 30     29     28    
 47      2     49    
 22     10     49    
 45     37     30    
 29     31      4    
 25     24     31

我希望这会有所帮助。