2016-08-30 37 views
0

我正在使用从空间网格系统获取的数据,例如划分为等间隔正方形(例如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,])] 

但是,我不能将它应用到我自己的数据,并不能找出原因。

编辑:最初,我以为有列命名的问题(即'名称'功能)。但是看起来可能会出现'output'行代码的问题,即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多个网站,并希望有一个更简洁的方法。我确信我保持了相同的结构,双重检查拼写和变量名称。任何人都能够对我可能做错的潜在事情发表任何意见吗?或者失败这个替代方法?没有为实际问题提供示例代码(我希望我能指出具体问题是什么,但在此之前原始示例是我能做到的最好的例子)!谢谢。

+0

我现在所能说的就是'names()'期待一个字符向量,其中包含尽可能多的元素作为'output'shas列。如果不是这种情况,这一行会抛出一个错误。 https://stat.ethz.ch/R-manual/R-devel/library/base/html/names.html – nilsole

+2

您可能希望将'mapply'包裹在'unlist'周围,因为它返回一个'list',并且你想要一个'vector':'''output < - df2 [,(df2 ['Row',]%in%df1 $ Row)&(df2 ['Column',]%in%df1 $ Column)]; (输出)< - df1 $ Site [unlist(mapply(function(r,c){which(r == df1 $ Row&c == df1 $ Column)},output [1,],output [2, ]))]'''。 – Abdou

+0

谢谢你的回应。但是,我曾尝试向'df2'添加重复列(这可能与我自己的数据有关),但代码在该示例中仍可正常运行。我尝试了unlisting,但是这并没有为我自己的数据赋予适当的列名到'df1'等价物中指定的相应单元格值(虽然在上面的例子中似乎仍然有效)。 –

回答

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

这是一个相当浓缩一段代码,所以我希望下面的解释将有助于澄清一些事情:通过每列

这基本上进入(与apply(df2, 2, FUN)),并检查它的前两行是否可以在df1中的每一行的第二和第三个元素中找到。如果满足条件,则它以data.frame格式返回该列,其列名称为中的值df1;否则返回空列(带有NA)。然后将这些列与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 

我希望这有助于。

+0

这个例子和我自己的数据都完美地工作,确实正是我所需要的!非常感谢! –

+0

太好了!我很高兴这有帮助。 – Abdou

相关问题