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