21

我有一个包含 9 个样本(行)和 51608 个变量(列)的数据集,每当我尝试对其进行缩放时,我都会不断收到错误消息:

这工作正常

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))

同样的错误。数字数据?

    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+ 给出错误。不知道这是否意味着这是一个普遍的问题,或者这是否只是碰巧捕获了有问题的列。仍然会很高兴听到是否有人有任何想法,因为只要没有变量全为零(或以另一种方式保持不变),这应该可以正常工作。

4

3 回答 3

33

我认为您没有正确寻找零方差列。让我们尝试一些虚拟数据。首先,一个可接受的矩阵: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

让我们尝试缩放和未缩放的 PCA oopsmat

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[ , which(apply(oopsmat, 2, var) != 0)]

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

于 2016-10-29T08:23:45.173 回答
5

除了乔的回答之外,只需检查数据框中列的类是否为数字。

如果有整数,那么您将得到 0 的方差,从而导致缩放失败。

因此,如果,

class(my_df$some_column)

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

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

希望这可以帮助某人。

于 2018-12-13T12:32:12.733 回答
4

The error is because one of the column has constant values.

Calculate standard deviation of all the numeric cols to find the zero variance variables.

If the standard deviation is zero, you can remove the variable and compute pca

于 2020-02-24T06:39:54.447 回答