R-Converting Incidence矩阵(csv文件)到边缘列表格式

时间:2018-05-10 19:47:47

标签: r csv matrix sna

我正在研究社交网络分析,并将使用Ucinet绘制网络图。为此,我必须将csv文件转换为边缘列表格式。将邻接矩阵转换为边缘列表是成功的。但是,很难将关联矩阵转换为边缘列表格式。

  1. csv文件(' some.csv')我有一个像这样的关联矩阵:

        A  B  C  D
    a   1  0  3  1
    b   0  0  0  2
    c   3  2  0  1
    
  2. 将邻接矩阵转换为边缘列表的代码如下:

    x<-read.csv("C:/.../something.csv", header=T, row.names=1)
    net<-as.network(x, matrix.type='adjacency', ignore.eval=FALSE, names.eval='dd', loops=FALSE)
    el<-edgelist(net, attrname='dd')
    write.csv(el, file='C:/.../result.csv')
    
  3. 现在它只能成功加载文件。我试着按照上面的方法,但是我收到了一个错误。

    y<-read.csv("C:/.../some.csv", header=T, row.names=1)
    net2<-network(y, matrix.type='incidence', ignore.eval=FALSE, names.eval='co', loops=FALSE)
    Error in network.incidence(x, g, ignore.eval, names.eval, na.rm, edge.check) : 
    

    提供的关联矩阵具有空的头/尾列表。 (你有没有得到正确的指示?)

  4. 我希望以这种方式看到结果:

    a A 1
    a C 3
    a D 1
    b D 2
    c A 3
    c B 2
    c D 1
    

    我试图将值设为错误,但我无法得到我想要的结果。 感谢您对此提供任何帮助。

1 个答案:

答案 0 :(得分:0)

这是您的数据:

inc_mat <- matrix(
  c(1, 0, 3, 1,
    0, 0, 0, 2,
    3, 2, 0, 1),
  nrow = 3, ncol = 4, byrow = TRUE
  )
rownames(inc_mat) <- letters[1:3]
colnames(inc_mat) <- LETTERS[1:4]

inc_mat
#>   A B C D
#> a 1 0 3 1
#> b 0 0 0 2
#> c 3 2 0 1

这里有个通用的功能可以解决问题:

as_edgelist.weighted_incidence_matrix <- function(x, drop_rownames = TRUE) {
  melted <- do.call(cbind, lapply(list(row(x), col(x), x), as.vector)) # 3 col matrix of row index, col index, and `x`'s values

  filtered <- melted[melted[, 3] != 0, ] # drop rows where column 3 is 0

                                                       # data frame where first 2 columns are...
  df <- data.frame(mode1 = rownames(x)[filtered[, 1]], # `x`'s rownames, indexed by first column in `filtered``
                   mode2 = colnames(x)[filtered[, 2]], # `x`'s colnames, indexed by the second column in `filtered`
                   weight = filtered[, 3],             # the third column in `filtered`
                   stringsAsFactors = FALSE)

  out <- df[order(df$mode1), ] # sort by first column

  if (!drop_rownames) {
    return(out)
  }
  `rownames<-`(out, NULL)
}

试试看:

el <- as_edgelist.weighted_incidence_matrix(inc_mat)
el
#>   mode1 mode2 weight
#> 1     a     A      1
#> 2     a     C      3
#> 3     a     D      1
#> 4     b     D      2
#> 5     c     A      3
#> 6     c     B      2
#> 7     c     D      1

这是您想要的结果:

control_df <- data.frame(
  mode1 = c("a", "a", "a", "b", "c", "c", "c"),
  mode2 = c("A", "C", "D", "D", "A", "B", "D"),
  weight = c(1, 3, 1, 2, 3, 2, 1),
  stringsAsFactors = FALSE
  )

control_df
#>   mode1 mode2 weight
#> 1     a     A      1
#> 2     a     C      3
#> 3     a     D      1
#> 4     b     D      2
#> 5     c     A      3
#> 6     c     B      2
#> 7     c     D      1

它们匹配吗?

identical(control_df, el)
#> [1] TRUE