【问题标题】:how to create a frequency matrix from a dataframe如何从数据帧创建频率矩阵
【发布时间】:2021-08-29 19:30:57
【问题描述】:

说我有 df:

df <- data.frame(cell = c("c1", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"),
                 layer = c("L1", "L2", "L1", "L2", "L3", "L3", "L4", "L4", "L3"))
> df
  cell layer
1   c1    L1
2   c1    L2
3   c2    L1
4   c3    L2
5   c4    L3
6   c5    L3
7   c6    L4
8   c7    L4
9   c8    L3

我将如何创建一个频率矩阵,如:

> table(df$cell, df$layer)
    
     L1 L2 L3 L4
  c1  1  1  0  0
  c2  1  0  0  0
  c3  0  1  0  0
  c4  0  0  1  0
  c5  0  0  1  0
  c6  0  0  0  1
  c7  0  0  0  1
  c8  0  0  1  0

但是在for循环中?我试过类似的东西:

> for(layer in unique(df$layer)){
+   df[paste(layer)] <- ifelse(df$layer == layer, 1, 0)
+ }
> df
  cell layer L1 L2 L3 L4
1   c1    L1  1  0  0  0
2   c1    L2  0  1  0  0
3   c2    L1  1  0  0  0
4   c3    L2  0  1  0  0
5   c4    L3  0  0  1  0
6   c5    L3  0  0  1  0
7   c6    L4  0  0  0  1
8   c7    L4  0  0  0  1
9   c8    L3  0  0  1  0

但它会对行进行一次加热并将其添加回原始数据帧... 我正在查看base:::table 的源代码,但找不到我感兴趣的部分。有没有办法“推”入一个空矩阵? 类似:

newMat <- Matrix(0, nrow = length(unique(df$cell)), ncol=length(unique(df$layer)))
for (i in 1:length(unique(df$cell))){
  for (j in 1:length(unique(df$layer)))){
    newMat[i,j] <- ....
  }
}

只是不知道如何完成它...谢谢! 预期输出,矩阵形式:

     L1 L2 L3 L4
  c1  1  1  0  0
  c2  1  0  0  0
  c3  0  1  0  0
  c4  0  0  1  0
  c5  0  0  1  0
  c6  0  0  0  1
  c7  0  0  0  1
  c8  0  0  1  0

【问题讨论】:

  • 您还可以添加预期的输出吗?
  • @Cole,刚刚添加,对此感到抱歉。谢谢!
  • 谢谢。而不是table(df$cell, df$layer),您希望循环完成?抱歉,我知道你这么说,但大多数问题更多的是相反 - 我如何矢量化循环。
  • @Cole 我正在使用一些参考 python 代码,这有点相同:` # Create adjacency matrix def compute_adjacency(pairs, idx): adj = np.zeros((n, n))对于成对的配对: l, r = tuple(pair) i = idx[l] j = idx[r] adj[i,j] = 1 adj[j,i] = 1 return adj` 我不知道怎么做但是,要在 R 中执行此操作。鉴于我的数据集略有不同,我想到的最接近的是 for 循环,但对于我的情况
  • 对不起,我对 stackoverflow 也不是很熟悉,所以最后一条评论的格式很糟糕。

标签: r dataframe matrix


【解决方案1】:

这是使用循环的一种方法:

df <- data.frame(cell = c("c1", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8"),
                 layer = c("L1", "L2", "L1", "L2", "L3", "L3", "L4", "L4", "L3"))


cells = unique(df$cell)
layers = unique(df$layer)

res = matrix(0L, 
             nrow = length(cells),
             ncol = length(layers),
             dimnames = list(cells, layers))

for (i in seq_along(cells)) {
  cols = match(df[df$cell == cells[i], 'layer'], layers)
  res[i, cols] = 1L
}

res

##    L1 L2 L3 L4
## c1  1  1  0  0
## c2  1  0  0  0
## c3  0  1  0  0
## c4  0  0  1  0
## c5  0  0  1  0
## c6  0  0  0  1
## c7  0  0  0  1
## c8  0  0  1  0

最大的两件事是,由于我们需要多次使用唯一的celllayers,分配给一个变量而不是多次使用unique 可以提高性能。然后,这个match(df[df$cell == cells[i], ...]) 调用用于确定存在哪些层,以便我们可以将1 分配给它们。

注意,我根本不会这样做。我建议使用table 或某种重塑机制。

【讨论】:

  • 使用table是因为效率更高?
  • 应该更有效率。请注意,df$cell == cells[i] 主要是按活动分组。也就是说,如果我们直接分组,我们只会通过df$cell 向量或多或少一次。使用过滤器方法,我们通过df$cell 传递cell 的唯一元素的数量。我主要是想让每个帖子更像一个循环。
  • 啊好吧,我明白了。谢谢!那么我会坚持使用 table(),但感谢你展示了 for 循环和 match 函数,我不知道
猜你喜欢
  • 2017-05-09
  • 2022-11-10
  • 1970-01-01
  • 2017-12-17
  • 1970-01-01
  • 2018-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多