【问题标题】:R: Multiplying elements of data frame with neighboursR:将数据框的元素与邻居相乘
【发布时间】:2015-05-17 15:28:31
【问题描述】:

我有一个 300x300 元素的数据框。它们中的每一个都是 -1 或 +1:

     [,1]   [,2]   [,3]  
[1,]   1     -1     -1   
[2,]   1      1      1  
[3,]  -1     -1      1  
[4,]   1      1     -1

我想要的是遍历我的数据框,并将每个值与每个相邻值相乘。
即:
对于原始数据框中的元素 [1,1],我想要 [1,1]、[1,2] 和 [2,1] 的乘积
对于原始数据框中的元素 [2,2],我想要 [2,2]、[1,2]、[2,1]、[2,3] 和 [3,2] 的乘积。

我尝试创建 4 个新数据帧,每个数据帧分别向右、向左、向上和向下移动 1 个元素:

x_up <- shift(x, 1, dir='up')
x_up <- as.array(x_up)
dim(x_up) <- dims
x_down <- shift(x, 1, dir='down')
x_down <- as.array(x_down)
dim(x_down) <- dims
x_left <- shift(x, 1, dir='left')
x_left <- as.array(x_left)
dim(x_left) <- dims
x_right <- shift(x, 1, dir='right')
x_right <- as.array(x_right)
dim(x_right) <- dims

其中 x 是我的原始数据框。
我可以看到,当我使用这种方法时,新的数据框并没有正确地移位;其中更多是相同的。我用相同的()检查了这个。

还有其他方法可以解决我的问题吗?

编辑:
shift() 属于 'binhf' 库

【问题讨论】:

    标签: r


    【解决方案1】:

    我认为可能有更聪明的方法可以做到这一点,但标准方法是迭代每个元素并使其周围环境相乘。

    开始于:

    mat <- matrix(c(1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1), ncol=3)
    

    为了避免正边距出现问题,您必须添加一列和一行1作为边距(乘法时正1不会有问题,如果您求和,则它必须是@例如 987654323@'s)。

    mat2 <- addmargins(mat, FUN=function(x) 1)
    

    现在您创建一个空矩阵来保存输出,然后迭代元素并乘以相邻元素。

    out <- matrix(nrow=nrow(mat), ncol=ncol(mat))
    for (i in 1:nrow(mat)) {
      for (j in 1:ncol(mat)) {
        out[i,j] <- prod(mat[i,j], mat2[i-1, j], mat2[i, j-1], mat2[i+1, j], mat2[i, j+1])
      }
    }
    

    导致:

    > out
         [,1] [,2] [,3]
    [1,]   -1    1    1
    [2,]   -1    1   -1
    [3,]    1    1    1
    [4,]   -1    1   -1
    

    对于 300x300 矩阵,这花费了不到一秒的时间,所以对您来说可能已经足够了。

    【讨论】:

    • @user20650 我忘了乘以元素本身,已修复,谢谢。
    • 我收到一个错误:x2[i - 1, j] 中的错误:维数不正确。我的数据在一个大数组中 - 这个解决方案是否适用于它,或者我应该转换它吗?
    • 大数组是什么意思?如果它有 2 个维度,则它是一个矩阵。如果没有,代码将失败,因为它试图访问维度ij(行/列)。
    • 这可能是我创建数据框时出现的问题。我已经导入了一个二进制 png 文件,我可以看到它作为一个维度为 300 300 3 的数组导入。我正在尝试将其转换为 300x300 的矩阵并重新运行代码。很抱歉在询问之前没有这样做。
    • @MadsObi 哦,当您以二进制形式读取图像时,确实会发生这种情况。这是某种图像平滑吗?
    【解决方案2】:

    这应该可以解决问题:

    ind <- which(x==x, arr.ind=TRUE) # index matrix
    
    # find distances (need distances of 1 or 0) 
    dist.mat <- as.matrix(dist(ind))
    inds2mult <- apply(dist.mat, 1, function(ii) which(ii <= 1))
    
    # get product of each list element in inds2mult
    # and reform into appropriate matrix
    matrix(
        sapply(inds2mult, function(ii) prod(unlist(x)[ii])),
        ncol=ncol(x))
    
    #     [,1] [,2] [,3]
    #[1,]   -1    1    1
    #[2,]   -1    1   -1
    #[3,]    1    1    1
    #[4,]   -1    1   -1
    

    要解决在调用dist 时出现大矩阵的内存问题,您可以尝试fields 包中的fields.rdist.near 函数(增量值为1):

    x <- matrix(rep(-1, 300*300), ncol=300)
    
    ind <- which(x==x, arr.ind=TRUE) # index matrix
    
    library(fields)
    ind.list <- fields.rdist.near(ind, delta=1) # took my computer ~ 15 - 20 seconds
    
    inds2mult <- tapply(ind.list$ind[,2], ind.list$ind[,1], list)
    
    matrix(
        sapply(inds2mult, function(ii) prod(unlist(x)[ii])),
        ncol=ncol(x))
    

    fields.rdist.near 帮助页面中的 delta 参数:

    阈值距离。所有被更多分隔的点对 距离上的 delta 被忽略。

    【讨论】:

    • 我喜欢这个,但dist 随着矩阵大小的增加变得相当昂贵......我的旧 lappie 内存不足,无法使用 300x300 矩阵
    • @user20650 糟糕,应该在发布之前尝试使用更大的矩阵。我会努力改进的。
    • 我收到一个错误:无法分配大小为 271.6 Gb 的向量,因此它可能不适用于我的数据框。
    • @MadsObi 请参阅fields.rdist.near 方法以避免分配问题。
    • @Frank:我读得很轻松,因为 Molx 的回答对我有用。不过我很感谢你的回答!
    猜你喜欢
    • 2018-12-01
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多