2016-08-30 35 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

相關問題