代码之家  ›  专栏  ›  技术社区  ›  James White

基于两个独立数据帧的值子设置列的问题

  •  0
  • James White  · 技术社区  · 8 年前

    我使用的是从空间网格系统中获得的数据,例如一个城市被划分为等距的正方形(例如250m2的单元)。每个单元格都有一个唯一的列和行编号,以及关于这个250m2广场内所包含区域的相应数字信息(例如整个城市中每个单元格的温度)。在整个网格区域(或示例城市)内,我有各种研究地点,并且我知道它们的位置(即每个地点所在的单元格行和列)。我有一个包含城市内所有单元格信息的数据框,但我想将其子集化,以仅包含我的研究地点所在单元格的信息。我之前问过一个关于这个的问题 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,])]
    

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

    编辑:最初,我认为列命名有问题(即“名称”函数)。但似乎“输出”代码行可能存在问题,其中包含了不应该包含的来自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多个网站,希望能有一种更简洁的方式。我确信我保持了相同的结构、拼写和变量名。有人能解释我可能做错的潜在事情吗?或者用另一种方法失败?

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

    1 回复  |  直到 8 年前
        1
  •  1
  •   Abdou    8 年前

    我能看到的唯一明显的问题是 mapply 没有被包裹起来 unlist . 返回一个 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,]))]
    

    编辑:

    如果目标是获取前2行与中给定行的第2和第3个元素匹配的列 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) )并检查其前2行是否可以在中每行的第2和第3个元素中找到 数据框1 。如果满足条件,则返回数据中的该列。其列名为值的帧格式 Site 在中的匹配行中 数据框1 ; 否则为空列(带有 NA 的)返回。然后将这些列与绑定在一起 do.call cbind ,然后强制转换为data.frame。最后,我们使用 Filter 函数删除其值为 不适用 的。

    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
    

    我希望这能有所帮助。