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

Posted

技术标签:

【中文标题】如何解决 prcomp.default():无法将常量/零列重新缩放为单位方差【英文标题】:How to solve prcomp.default(): cannot rescale a constant/zero column to unit variance 【发布时间】:2017-03-11 22:41:06 【问题描述】:

我有一个包含 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. 

在某个截止值(例如

【问题讨论】:

看看sum(!is.finite(scale(pca_data)))给你什么。 你解决了吗? 【参考方案1】:

我认为您没有正确寻找零方差列。让我们尝试一些虚拟数据。首先,一个可接受的矩阵: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[ , which(apply(oopsmat, 2, var) != 0)]

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

【讨论】:

我遇到了这个问题,我尝试了你的方法,找到了一些相关的列并删除了它们。我还检查了带有常量的列。但是,我仍然收到相同的错误消息,当我到达一个不恒定的数字列 (#111) 时,它首先出现。为什么会这样? 您是否检查过所有列都是数字的?请参阅下面@orrymr 的回答。【参考方案2】:

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

如果有整数,那么你会得到 0 的方差,导致缩放失败。

如果,

class(my_df$some_column)

是一个整数64,例如,那么做如下

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

希望这对某人有所帮助。

【讨论】:

为什么如果有整数,方差是0?【参考方案3】:

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

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

如果标准差为零,可以去掉变量,计算pca

【讨论】:

以上是关于如何解决 prcomp.default():无法将常量/零列重新缩放为单位方差的主要内容,如果未能解决你的问题,请参考以下文章

我无法将逻辑回归拟合到模型中。如何解决这个问题?

如何解决 TypeError:无法将系列转换为 <type 'float'>

如何解决“无法将依赖项 [...] 添加到模块 [...] 的配置‘默认’,因为此配置不存在”?

将 XML 插入 SQL Server 时如何解决“无法切换编码”错误

形状不匹配:无法将对象广播到单个形状如何解决python中的此类错误?

expo项目,无法通过扫描二维码将项目加载到iPhone,如何解决?