gpt4 book ai didi

R 计算数据帧或数组中相邻相同值的数量

转载 作者:行者123 更新时间:2023-12-04 20:43:38 25 4
gpt4 key购买 nike

我有一个来自河流底部的分类基质尺寸数据集。由于我收集数据的方式,我可以在空间上将它们排列成一个矩阵,其中保留了它们与邻居的关系(即,左侧、前面等)。一个示例如下所示:

     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

其中 P(n) 是从左到右横穿河流的横断面上的实际点测量值,T(n) 给出从上游到下游的横断面。如您所见,某些基质类型(特别是本示例中的基岩“BR”)具有比其他基质更大的相邻斑块。这在生态上是有意义的,而且可能不仅仅是样本中 BR 的百分比。

我的问题是:是否有一种简单的方法可以计算彼此相邻的相同类型的基板测量值的数量?请注意,角相邻也被认为是相邻的。

编辑以下非常有用的评论:

示例输出将是每种类型补丁的列表,以及每个补丁中的测量数量。它可能看起来像这样:
$BR  
[1] 9

$B
[1] 1 1

$C
[1] 4 3 1

$P
[1] 1 1

$G
[1] 1 1

$SI
[1] 3 2

最佳答案

一个有趣的小问题。我附上了一个解决方案,它应该适用于任何因素矩阵。它正在使用 foreachdata.table包,所以你可能想要安装它们。

它的工作原理是首先堆叠数据并将每个位置映射到一个值。然后它遍历原始矩阵,对邻居进行贪婪的自递归,但首先从堆叠矩阵中删除自己(避免多次计算自己)。

我不喜欢这个解决方案中的一些 for 循环,但考虑到与堆叠框架交互的加速,我没有看到一个简单的方法来解决它而不完全重新工作。更好的实现是使用像 synchronicity 这样的包在并行线程中运行它(可能通过补丁类型而不是位置)。在堆叠数据周围放置一个互斥锁(有人吗?)。
dcastreshape2 package 也是创建堆叠框架的好选择。

对于这个矩阵:

> 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

它给出了以下结果(看起来像你所要求的):
> patchesList
$G
[1] 1 1
$C
[1] 4 3 1
$P
[1] 1 1
$B
[1] 2 1
$SI
[1] 3 2
$BR
[1] 9
$CL
[1] 1

数据设置代码:
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))

堆叠原始数据(带有位置信息):
idxsFrame = expand.grid(1:nrow(d),1:ncol(d))
colnames(idxsFrame) = c("ri","cj")
idxsFrame$value = apply(idxsFrame,1,function(x) { d[x[["ri"]],x[["cj"]]] } )
require(data.table)
idxsFrame = data.table(idxsFrame)

设置输出列表:
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))
}
}

主循环:
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))
}
}
}

关于R 计算数据帧或数组中相邻相同值的数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21537439/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com