基于来自两个单独数据框的值对列进行子集化的问题
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.call
和 cbind
绑定在一起,然后强制转换为 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
希望对您有所帮助。
我正在使用从空间网格系统获得的数据,例如,一个城市被分成等距的正方形(例如 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.call
和 cbind
绑定在一起,然后强制转换为 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
希望对您有所帮助。