如何解决prcomp.default():无法将常量/零列重新调整为单位方差

时间:2016-10-29 01:39:36

标签: r matrix pca

我有一个包含51608个变量(列)的9个样本(行)的数据集,每当我尝试缩放它时,我都会收到错误:

这很好用

pca = prcomp(pca_data)

然而,

pca = prcomp(pca_data, scale = T)

给出

> Error in prcomp.default(pca_data, center = T, scale = T) : 
  cannot rescale a constant/zero column to unit variance

显然,发布一个可重复的例子有点困难。有什么想法可以达成协议吗?

寻找恒定列:

    sapply(1:ncol(pca_data), function(x){
               length = unique(pca_data[, x]) %>% length
             }) %>% table

输出:

    .
        2     3     4     5     6     7     8     9 
     3892  4189  2124  1783  1622  2078  5179 30741 

所以没有恒定的列。与NA'相同 -

    is.na(pca_data) %>% sum

    >[1] 0

这很好用:

    pca_data = scale(pca_data)

但之后两人仍然给出完全相同的错误:

    pca = prcomp(pca_data)
    pca = prcomp(pca_data, center = F, scale = F)

那么为什么我无法在这些数据上获得缩放的pca?好的,让我们100%确定它不是恒定的。

    pca_data = pca_data + rnorm(nrow(pca_data) * ncol(pca_data))

相同的错误。 Numierc数据?

    sapply( 1:nrow(pca_data), function(row){
      sapply(1:ncol(pca_data), function(column){
         !is.numeric(pca_data[row, column])
       })
     } ) %>% sum

仍然是同样的错误。我没有想法。

编辑:更多,至少要解决它。

稍后,仍然很难聚集这些数据,例如:

    Error in hclust(d, method = "ward.D") : 
      NaN dissimilarity value in intermediate results. 

在特定截止值下修剪值,例如< 1到零无效。最终工作的是修剪列中包含多于x个零的所有列。为#zeros< = 6工作,但是7+给出了错误。不知道这是否意味着这一般是一个问题,或者是否恰好碰到了一个有问题的专栏。仍然会很高兴听到有人有任何想法,因为只要没有变量全是零(或以其他方式不变),这应该可以正常工作。

3 个答案:

答案 0 :(得分:16)

我认为你没有正确地寻找零方差列。让我们尝试一些虚拟数据。首先,一个可接受的矩阵:10x100:

mat <- matrix(rnorm(1000, 0), nrow = 10)

一个零方差列。我们称之为oopsmat

const <- rep(0.1,100)
oopsmat <- cbind(const, mat)

oopsmat的前几个元素如下所示:

      const                                                                                               
 [1,]   0.1  0.75048899  0.5997527 -0.151815650  0.01002536  0.6736613 -0.225324647 -0.64374844 -0.7879052
 [2,]   0.1  0.09143491 -0.8732389 -1.844355560  0.23682805  0.4353462 -0.148243210  0.61859245  0.5691021
 [3,]   0.1 -0.80649512  1.3929716 -1.438738923 -0.09881381  0.2504555 -0.857300053 -0.98528008  0.9816383
 [4,]   0.1  0.49174471 -0.8110623 -0.941413109 -0.70916436  1.3332522  0.003040624  0.29067871 -0.3752594
 [5,]   0.1  1.20068447 -0.9811222  0.928731706 -1.97469637 -1.1374734  0.661594937  2.96029102  0.6040814

让我们在oopsmat上尝试按比例缩放和取消缩放的PCA:

PCs <- prcomp(oopsmat) #works
PCs <- prcomp(oopsmat, scale. = T) #not forgetting the dot
#Error in prcomp.default(oopsmat, scale. = T) : 
   #cannot rescale a constant/zero column to unit variance

因为如果它是无穷大,你不能除以标准偏差。要识别零方差列,我们可以使用which如下获取变量名称。

which(apply(oopsmat, 2, var)==0)
#const 
#1 

要从数据集中删除零方差列,您可以使用相同的apply表达式,设置方差不等于零。

oopsmat[ , apply(oopsmat, 2, var) != 0]

希望有助于使事情更清楚!

答案 1 :(得分:2)

错误是因为其中一列具有常量值。

计算所有数值列的标准偏差,以找到零方差变量。

如果标准偏差为零,则可以删除变量并计算pca

答案 2 :(得分:1)

除了Joe的答案,只需检查数据框中列的类是否为数字即可。

如果有整数,则方差为0,导致缩放失败。

如果

class(my_df$some_column)
例如,

是一个整数64,然后执行以下操作

my_df$some_column <- as.numeric(my_df$some_column)

希望这对某人有帮助。