如何在R中自动处理矩阵(数据帧)

时间:2015-08-16 10:04:07

标签: r matrix

我有一个41x41的相似性矩阵(或数据框),就像下面一样(我在附件中附上完整版本):

     V1    V2      V3      V4      V5      V6
 V1   1    0.068   0.211   0.285   0.198   0.047
 V2  0.068   1     0.851   0.450   0.277   0.014
 V3  0.211  0.851     1    0.660   0.420   0.113
 V4  0.285  0.450  0.660      1    0.896   0.466
 V5  0.198  0.277  0.420    0.896    1     0.241
 V6  0.047  0.014  0.113    0.466   0.241     1

我想为每个向量(Vx)建立一个推荐列表,第一个地方最相似,最后一个不同。所以我认为我需要提取两列(或两行),通过减少对值进行排序,并提取列名称。 但是,当我尝试自动选择列时,它不起作用。

ms<-readLines("E:/exp/ccsm.txt", encoding = "UTF-8")
d = as.data.frame(ms)
for(dcol in 2:length(ms))
 {
   temp<-d[,c(1,dcol)]
   nlist<-temp[order(d[,dcol], decreasing=T)]
   lname<-nlist[,1]
 }
Show Traceback
Rerun with Debug
Error in `[.data.frame`(d, , c(1, dcol)) : undefined columns selected

似乎变量不能是列/行号?但是可能需要更大的相似性矩阵才能进行处理。如果它无法通过某种循环实现,那将是一场灾难。 我想知道你是否可以就解决这个问题给我一些建议。如果您能尽快回复,我将不胜感激。期待收到你的回复。

1 个答案:

答案 0 :(得分:1)

在我看来,您的主要问题是您没有正确地将文件读入数据框。

我将您的示例数据保存到我的R会话的pwd中的ccsm.txt,然后执行以下操作:

ms <- readLines('ccsm.txt',encoding='UTF-8');
ms;
## [1] "     V1    V2      V3      V4      V5      V6"
## [2] " V1   1    0.068   0.211   0.285   0.198   0.047"
## [3] " V2  0.068   1     0.851   0.450   0.277   0.014"
## [4] " V3  0.211  0.851     1    0.660   0.420   0.113"
## [5] " V4  0.285  0.450  0.660      1    0.896   0.466"
## [6] " V5  0.198  0.277  0.420    0.896    1     0.241"
## [7] " V6  0.047  0.014  0.113    0.466   0.241     1"
d <- as.data.frame(ms);
d;
##                                                 ms
## 1         V1    V2      V3      V4      V5      V6
## 2  V1   1    0.068   0.211   0.285   0.198   0.047
## 3  V2  0.068   1     0.851   0.450   0.277   0.014
## 4  V3  0.211  0.851     1    0.660   0.420   0.113
## 5  V4  0.285  0.450  0.660      1    0.896   0.466
## 6  V5  0.198  0.277  0.420    0.896    1     0.241
## 7   V6  0.047  0.014  0.113    0.466   0.241     1
names(d);
## [1] "ms"
dim(d);
## [1] 7 1
sapply(d,class);
##       ms
## "factor"

正如您所看到的,您的readLines() / as.data.frame()次调用产生了一个7 x 1的data.frame,其中一列包含文件原始文本行的因子。

相反,您需要使用read.table()(还有其他选项,例如来自fread()data.table):

d <- read.table('ccsm.txt');
d;
##       V1    V2    V3    V4    V5    V6
## V1 1.000 0.068 0.211 0.285 0.198 0.047
## V2 0.068 1.000 0.851 0.450 0.277 0.014
## V3 0.211 0.851 1.000 0.660 0.420 0.113
## V4 0.285 0.450 0.660 1.000 0.896 0.466
## V5 0.198 0.277 0.420 0.896 1.000 0.241
## V6 0.047 0.014 0.113 0.466 0.241 1.000
names(d);
## [1] "V1" "V2" "V3" "V4" "V5" "V6"
dim(d);
## [1] 6 6
sapply(d,class);
##        V1        V2        V3        V4        V5        V6
## "numeric" "numeric" "numeric" "numeric" "numeric" "numeric"

不幸的是,您的代码仍然不起作用:

for (dcol in 2:length(ms)) {
    temp <- d[,c(1,dcol)];
    nlist <- temp[order(d[,dcol],decreasing=T)];
    lname <- nlist[,1];
};
## Error in `[.data.frame`(temp, order(d[, dcol], decreasing = T)) :
##   undefined columns selected

这里有两个问题。首先,ms包含文件的原始行文本,编号为7,因为包含了标题行。但是文件中只有6行。因此d[,c(1,dcol)]dcol达到7时失败。

但是dcol永远不会达到7,因为在第一次迭代中temp[order(d[,dcol],decreasing=T)]失败了。这是因为temp是一个data.frame,因为它是从d的两列切片中分配的。但是您使用单个参数对temp进行索引,该参数为基础列表编制索引,该列表只有两个组件。 order()调用的返回值由整数1到6组成,因为它在d列上运行(d中有6行),因此整数3到6对temp data.frame。

下面的双组件列表都超出范围

这是我如何计算所需的输出:

apply(d,1,order,decreasing=T);
##      V1 V2 V3 V4 V5 V6
## [1,]  1  2  3  4  5  6
## [2,]  4  3  2  5  4  4
## [3,]  3  4  4  3  3  5
## [4,]  5  5  5  6  2  3
## [5,]  2  1  1  2  6  1
## [6,]  6  6  6  1  1  2

如果您想要推荐的矢量而不是索引的名称,您可以这样做:

apply(d,1,function(x) names(d)[order(x,decreasing=T)]);
##      V1   V2   V3   V4   V5   V6
## [1,] "V1" "V2" "V3" "V4" "V5" "V6"
## [2,] "V4" "V3" "V2" "V5" "V4" "V4"
## [3,] "V3" "V4" "V4" "V3" "V3" "V5"
## [4,] "V5" "V5" "V5" "V6" "V2" "V3"
## [5,] "V2" "V1" "V1" "V2" "V6" "V1"
## [6,] "V6" "V6" "V6" "V1" "V1" "V2"

如果你不喜欢第一排,因为它必然会排在&#34; self&#34;矢量最高,您可以使用...[-1,]将其编入索引。