我有数据数据1,它有一个逗号分隔的文本列c.2,看起来像
c.1 c.2
A IN, CA, IL, NY
B NJ, IN,AR
C DC, NY
D TX, AR, IN我使用c.1创建一个空的邻接矩阵Aij
A B C D
A 0 0 0 0
B 0 0 0 0
C 0 0 0 0
D 0 0 0 0如果逗号分隔的文本相同,我想在逗号分隔的列中搜索类似的文本,c.2用1重新分配我的邻接矩阵Aij。例如,在数据1中,c.1列的A、B和D中有“in”,我将在Aij中用1重新分配AB、AD。类似地,“NY”在A中,C和我将分配另一个AC=1。“AR”在B和D中,我将赋值给BD=1,然后我将添加值,我的新矩阵看起来就像,
A B C D
A 0 1 1 1
B 1 0 0 1
C 1 0 0 0
D 1 1 0 0 如何读取普通文本并重新分配邻接矩阵,而不将c.2列拆分为多个子列?
发布于 2015-08-11 00:56:27
您确实需要在某个时候分离c.2,这样您就可以比较这些值。否则,您可以尝试一些正则表达式技巧,但我怀疑这会更快,然后您必须担心转义您的文本,以使正则表达式安全。
我确信有很多方法可以做到这一点(可能有一些内置的包具有更快的编码方法),但是这个解决方案的关键是基R的combn函数。
# recreate your dataframe
x <- data.frame(c.1=LETTERS[1:4],
c.2=c('IN, CA, IL, NY', 'NJ, IN,AR', 'DC, NY', 'TX, AR, IN'),
stringsAsFactors=F)在这里,我们将c2列拆分为一个列表,而不是一个数据格式,因为每行中的条目数并不相同。
# split up the comma values
bits <- strsplit(x$c.2, ', ?')构造一个0的矩阵来保持你的邻接矩阵:
adj <- matrix(0, nrow=nrow(x), ncol=nrow(x), dimnames=list(x$c.1, x$c.1))首先,要认识到你的邻接矩阵是对称的,如果(B和A)有一个共同的元素,那么(A和B)也是一样的。因此,我们只需要计算矩阵的上半部分或下半部分的公共分量数,然后就可以对其进行镜像。
关键是combn(1:4, m=2, FUNCTION)。首先尝试combn(1:4, m=2),您将看到它将数字1:4的组合组成一个矩阵,即将所有坐标的矩阵转化为邻接矩阵(不包括对角线)。您可以执行类似expand.grid(1:4, 1:4)的操作,但这将包括长度为1:4的排列,也就是说,它将同时包含(第1行,第3列)和(第3行,第1列),我们先前确定的值无论如何都是相同的。因此,我们使用combn只在邻接矩阵的上(或下)半处生成坐标。
然后,通过在FUN上使用intersect,我们可以简单地看到A列中有多少元素在B列中。
最后,我们使用adj[lower.tri(adj, diag=F)]将值赋值到邻接矩阵的下半部(<-按列分配,我们的坐标是逐行的,所以我们使用下半部,而不是上半段):
adj[lower.tri(adj, diag=F)] <-
combn(1:nrow(x), m=2, function (coords) {
length(intersect(bits[[coords[1]]], bits[[coords[2]]]))
})最后,我们使用下半部值填充矩阵的上半部分( t(adj)是一些花哨的基础,因为它是按列分配的)。
adj[upper.tri(adj)] <- t(adj)[upper.tri(adj)]
> adj
A B C D
A 0 1 1 1
B 1 0 0 2
C 1 0 0 0
D 1 2 0 0这是一个很长的答案,因为所有的解释,但实际上只有3行:
adj <- matrix(0, nrow=nrow(x), ncol=nrow(x), dimnames=list(x$c.1, x$c.1)
adj[lower.tri(adj, diag=F)] <-
combn(1:nrow(x), m=2, function (coords) {
length(intersect(bits[[coords[1]]], bits[[coords[2]]]))
})
adj[upper.tri(adj)] <- t(adj)[upper.tri(adj)]https://stackoverflow.com/questions/31931129
复制相似问题