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

Problems subsetting columns based on values from two separate dataframes

我正在使用从空间网格系统获得的数据,例如,一个城市被分成等距的正方形(例如 250 平方米的单元格)。每个单元格都有一个唯一的列和行号,以及关于这个 250 平方米正方形内包含的区域的相应数字信息(比如整个城市每个单元格的温度)。在整个网格化部分(或示例城市)中,我有各种研究地点并且我知道它们位于何处(即每个地点位于哪个单元格行和列中)。我有一个包含城市内所有单元格信息的数据框,但我想将其子集化为仅包含来自我的研究地点所在单元格的信息。我之前就这个“”问过一个问题。这里又是一些示例代码:

###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,])]

但是,我无法将其应用于我自己的数据,也无法弄清楚原因。

编辑:最初,我认为命名列(即 'names' 函数)有问题。但看起来 'output' 代码行可能存在问题,其中列被包含在 df2 中,而这些列不应该包含在 df2 中(即输出包含 df2 中的列,其中包含 df1 中未指定的列号和行号).

我也试过:

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

但是当使用我自己的(看似可比较的)数据时,我没有从 'df1' 等效项中指定的所有单元格中获取信息(尽管在上面的示例数据中再次工作正常)。如果我单独进行每个研究站点,我可以获得自己的数据。

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 多个网站,希望有一种更简洁的方式。我确信我保持了相同的结构,仔细检查了拼写和变量名。谁能阐明我可能做错的潜在事情?还是失败了另一种方法?

很抱歉没有提供实际问题的示例代码(我希望我能指出具体问题是什么,但在那之前我能做的最好的就是原始示例)!谢谢你。

我能看到的唯一明显的问题是 mapply 没有环绕在 unlist 周围。 mapply returns a 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 中每一行的第二和第三个元素中找到.如果满足条件,则 returns 该列以 data.frame 格式,其列名是 df1 中匹配行中 Site 的值;否则返回一个空列(带有 NA'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

希望对您有所帮助。