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

Bri*_*son 13 r matrix pca prcomp

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

这很好用

pca = prcomp(pca_data)
Run Code Online (Sandbox Code Playgroud)

然而,

pca = prcomp(pca_data, scale = T)
Run Code Online (Sandbox Code Playgroud)

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

显然,发布一个可重复的例子有点困难.任何想法可能是什么交易?

寻找恒定列:

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

输出:

    .
        2     3     4     5     6     7     8     9 
     3892  4189  2124  1783  1622  2078  5179 30741 
Run Code Online (Sandbox Code Playgroud)

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

    is.na(pca_data) %>% sum

    >[1] 0
Run Code Online (Sandbox Code Playgroud)

这很好用:

    pca_data = scale(pca_data)
Run Code Online (Sandbox Code Playgroud)

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

    pca = prcomp(pca_data)
    pca = prcomp(pca_data, center = F, scale = F)
Run Code Online (Sandbox Code Playgroud)

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

    pca_data = pca_data + rnorm(nrow(pca_data) * ncol(pca_data))
Run Code Online (Sandbox Code Playgroud)

同样的错误.Numierc数据?

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

还是一样的错误.我没有想法.

编辑:更多和一个黑客至少解决它.

之后,仍然难以聚集这些数据,例如:

    Error in hclust(d, method = "ward.D") : 
      NaN dissimilarity value in intermediate results. 
Run Code Online (Sandbox Code Playgroud)

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

Joe*_*Joe 23

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

mat <- matrix(rnorm(1000, 0), nrow = 10)
Run Code Online (Sandbox Code Playgroud)

并且具有零方差列.我们称之为oopsmat.

const <- rep(0.1,100)
oopsmat <- cbind(const, mat)
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

让我们尝试使用缩放和未缩放的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
Run Code Online (Sandbox Code Playgroud)

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

which(apply(oopsmat, 2, var)==0)
#const 
#1 
Run Code Online (Sandbox Code Playgroud)

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

oopsmat[ , apply(oopsmat, 2, var) != 0]
Run Code Online (Sandbox Code Playgroud)

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


小智 6

该错误是因为其中一列具有恒定值。

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

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


orr*_*ymr 5

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

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

因此,如果,

class(my_df$some_column)
Run Code Online (Sandbox Code Playgroud)

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

my_df$some_column <- as.numeric(my_df$some_column)
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助某人。

  • 如果存在整数,为什么方差为 0? (2认同)