R计算数据帧或数组中相邻相同值的数目
我有一个来自河流底部的分类基质尺寸数据集。由于我收集数据的方式,我可以在空间上将它们排列成一个矩阵,在这个矩阵中它们与邻居的关系得以保留(例如,在左边、前面等)。示例如下所示:R计算数据帧或数组中相邻相同值的数目,r,dataframe,geospatial,data.table,R,Dataframe,Geospatial,Data.table,我有一个来自河流底部的分类基质尺寸数据集。由于我收集数据的方式,我可以在空间上将它们排列成一个矩阵,在这个矩阵中它们与邻居的关系得以保留(例如,在左边、前面等)。示例如下所示: P.1 P.2 P.3 P.4 P.5 T 1 G C C P C T 2 P C B G C T 3 SI SI C B C T 4 SI BR BR SI SI T 5 BR CL BR BR B T 6 BR B
P.1 P.2 P.3 P.4 P.5
T 1 G C C P C
T 2 P C B G C
T 3 SI SI C B C
T 4 SI BR BR SI SI
T 5 BR CL BR BR B
T 6 BR BR BR BR C
$BR
[1] 9
$B
[1] 1 1
$C
[1] 4 3 1
$P
[1] 1 1
$G
[1] 1 1
$SI
[1] 3 2
式中,p(n)是从左至右穿过河流的横断面上的实际测量点,T(n)给出了从上游到下游的横断面。如您所见,一些基底类型(在本示例中,特别是基岩“BR”)的相邻面片比其他面片更大。这在生态学上是有意义的,可能不仅仅是样本中溴的百分比
我的问题是:有没有一种简单的方法来计算相邻的同一类型基板的测量数量?请注意,角相邻也被视为相邻
编辑以下非常有用的评论:
一个示例输出是每种类型的补丁的列表,以及每个补丁中的测量数量。可能是这样的:
P.1 P.2 P.3 P.4 P.5
T 1 G C C P C
T 2 P C B G C
T 3 SI SI C B C
T 4 SI BR BR SI SI
T 5 BR CL BR BR B
T 6 BR BR BR BR C
$BR
[1] 9
$B
[1] 1 1
$C
[1] 4 3 1
$P
[1] 1 1
$G
[1] 1 1
$SI
[1] 3 2
一个有趣的小问题。我附加了一个解决方案,它应该适用于任何因素矩阵。它使用的是
foreach
和data.table
软件包,因此您可能需要安装这些软件包
它的工作原理是首先堆叠数据并将每个位置映射到一个值。然后,它迭代原始矩阵,对相邻矩阵进行贪婪的自递归,但首先从堆叠矩阵中删除自身(避免多次计算自身)
我不喜欢这个解决方案中的一些for循环,但考虑到与堆叠帧交互的加速,如果不完全重新工作,我看不到一个简单的解决方法。更好的实现是在并行线程中运行(可能是通过补丁类型而不是位置),使用一个包,比如在堆叠的数据周围放置互斥锁(任何人?)
restrape2
包中的dcast
也是创建堆叠帧的好选项
对于该矩阵:
> d
P-1 P-2 P-3 P-4 P-5 P-6
T-1 G P SI SI BR BR
T-2 C C SI BR CL BR
T-3 C B C BR BR BR
T-4 P G B SI BR BR
T-5 C C C SI B C
它给出了以下结果(看起来像您要求的结果):
数据设置代码:
rm(list=ls())
d = strsplit("G C C P C P C B G C SI SI C B C SI BR BR SI SI BR CL BR BR B BR BR BR BR C"," ")[[1]]
d=d[-which(d=="")]
d=data.frame(matrix(d,nrow=5),stringsAsFactors=F)
rownames(d) = paste("T",1:5,sep="-")
colnames(d) = paste("P",1:6,sep="-")
levs = unique(unlist(d))
堆叠原始数据(包含位置信息):
设置输出列表:
patchesList = vector(mode="list",length=length(levs))
names(patchesList) = levs
require(foreach)
执行扫描的自递归函数:
scanSurroundTiles = function(tile)
{
surroundTiles = idxsFrame[ri>=(tile$ri-1) & ri <=(tile$ri+1) & cj>=(tile$cj-1) & cj<=(tile$cj+1),,drop=F]
baseMatches = surroundTiles[which(surroundTiles$value == tile$value),,drop=F]
if(nrow(baseMatches) < 1)
return(tile)
else
{
# not possible to do an apply(matches,1,scanSurroundTiles) because of overlap and self-recursiveness on deeper levels
newMatches <- foreach(mc = 1:nrow(baseMatches), .combine=rbind) %do% # mc = 2;
{
inIdxs = which(idxsFrame$ri==baseMatches$ri[mc] & idxsFrame$cj==baseMatches$cj[mc])
if(length(inIdxs)>0)
{ assign("idxsFrame",idxsFrame[-inIdxs,,drop=F],globalenv())
return(scanSurroundTiles(baseMatches[mc,,drop=F]))
} else
{ return(NULL) } # could have been removed from previous foreach
}
return(rbind(tile,newMatches))
}
}
scanSurroundTiles=功能(tile)
{
surroundTiles=idxsFrame[ri>=(tile$ri-1)&ri=(tile$cj-1)&cj 0)
{
idxsFrame您需要更精确地计算您想要计算的内容。对于您给出的示例,答案是什么?因此,以BR
为例,您希望9
与上面看到的每个值相关联,而SI
如果在左侧组中,每个值将被给出3
,如果在右侧组中,每个值将被给出2
o您想要一个如上所述的矩阵,或者设想这些矩阵的格式很长?或者每个相邻分组都有一个唯一的行,其中包含区域和类型变量?共享一个角点算相邻吗?您有一个很好的观点!好的,因此最有用的输出类型可能是单个面片的面片大小列表Corner关联是非常真实的关联,我认为它们是自然的,在90度角上是不相称的。上面的例子是:<代码> $BR< /代码>代码> [ 1 ] 9代码/代码> $b<代码> >代码> [ 1 ] 1 1 < /代码>代码> $c<代码>代码> [1 ]3 3 1 1
[1]1 1
$G
[1]1
[1]3 2
这有帮助吗?贴片的精确标识远不如其中的测量数量重要。为了检查自动输出,应B
不给出c(2,1)
,而c
应给出c(4,3,1)
?我几乎认为您应该将矩阵转换为空间多边形数据框
对象(每个单元都是多边形),然后使用UnionCascaded()进行聚合rgeos
中的
将尝试做一个示例,如果这仍然没有得到解决,我尝试了昨天提出的建议,但无法充分合并仅共享一个角的多边形:-P,因此我将避免发布它。
for(i in 1:nrow(d))
{
for(j in 1:ncol(d))
{
sourceTile = idxsFrame[ri==i & cj==j,,drop=F]
if(nrow(sourceTile) > 0)
{
idxsFrame <- idxsFrame[-which(idxsFrame$ri==sourceTile$ri & idxsFrame$cj==sourceTile$cj),,drop=F]
thisPatch = scanSurroundTiles(sourceTile)
# if you want to do some calc by patch (mean, sd) this is the place to do it by adding other info beyond the type in the stacked frame
patchesList[[thisPatch$value[1]]] = c(patchesList[[thisPatch$value[1]]],nrow(thisPatch))
}
}
}