Python 中的 R 命令 "which(apply(data, 2, var)==0)"

R command "which(apply(data, 2, var)==0)" in Python

我想知道如何编写 R 命令

which(apply(data, 2, var)==0)

... 在 Python.

现在我正在尝试 运行 一个 R 脚本来做 PCA。
但是,pca() 只接受非常量列(=方差不为 0)。
例如,只有 Col2 可以被接受为以下非常量列:

Col1 Col2 Col3
0.0  1.2  4.0
0.0  1.5  4.0
0.0  1.3  4.0
0.0  1.1  4.0

我以为我删除了所有常量列。
但是,我得到一个错误:

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

我用谷歌搜索并找到 this question 和 R 命令解决方案:

which(apply(oopsmat, 2, var)==0)

它对我有用。该命令指定哪些列仍然不变。
因此,我手动删除了列,R 脚本执行了 PCA。

现在我想在 Python 中做同样的事情。
在 Python 中如何编写此 R 命令?

############################################# ########

请不要阅读下文,否则会浪费您的时间。
我留下这个作为我问了一个愚蠢问题的证据:

注意:这个 R 命令很奇怪。
正如我所说,我已经从我的数据中删除了所有常量列。
这个 R 命令告诉以下列的方差是 0
(摘自大约 50,000 条数据):

:  
0  
0  
4  
0  
19  
0  
32  
61  
878  
4  
1  
13  
16  
14  
2  
4  
13  
:  

Excel的方差命令VAR.P的结果是231.4。
这甚至不接近于 0!
我不知道发生了什么,我在 Python.
中找不到这样的命令 所以,也请解释一下这种奇怪的行为。

*我忽略了删除所有异常值的代码,这就是为什么只剩下 0 的原因。

本质上,R 中的命令 apply(data, 2, var) 运行在二维结构上,例如矩阵或数据帧(但不建议后者)以计算所有列的方差:

数据框

set.seed(73120)

random_df <- data.frame(
  num1 = runif(500, 1, 100),
  num2 = runif(500, 1, 100),
  num3 = runif(500, 1, 100),
  num4 = runif(500, 1, 100),
  num5 = runif(500, 1, 100)
)

apply(random_df, 2, var)
#     num1     num2     num3     num4     num5 
# 822.9465 902.5558 782.4820 804.1448 830.1097 

一旦应用 which,命名向量(即一维数组)的索引将根据逻辑 returned。

which(apply(random_df, 2, var) > 900)
# num2 
#    2 

矩阵

set.seed(73120)

random_mat <- replicate(5, runif(500, 1, 100))

apply(random_mat, 2, var)
# [1] 822.9465 902.5558 782.4820 804.1448 830.1097

which(apply(random_mat, 2, var) > 900)
# [1] 2

Pandas

在Python中,使用pandas(数据分析库),等同于应用DataFrame.apply with axis set to index to run operations on all columns. Equivalently, you can run DataFrame.aggregate。 return 是一个 Pandas 系列,类似于 R 的命名向量作为一维数组。

import numpy as np
import pandas as pd

np.random.seed(7312020)

random_df = pd.DataFrame({'num1': np.random.uniform(1, 100, 500),
                          'num2': np.random.uniform(1, 100, 500),
                          'num3': np.random.uniform(1, 100, 500),
                          'num4': np.random.uniform(1, 100, 500),
                          'num5': np.random.uniform(1, 100, 500)
                         })

agg1 = random_df.apply('var', axis='index')
print(agg1)
# num1    828.538378
# num2    810.755215
# num3    820.480400
# num4    811.728108
# num5    885.514924
# dtype: float64

agg2 = random_df.aggregate('var')
print(agg2)
# num1    828.538378
# num2    810.755215
# num3    820.480400
# num4    811.728108
# num5    885.514924
# dtype: float64

R 的 which 可以通过简单的括号 [...](在 R 中也可用)、.locwhere(保持原始尺寸)来实现:

agg[agg > 850]
# num5    885.514924
# dtype: float64

agg.loc[agg > 850]
# num5    885.514924
# dtype: float64

agg.where(agg > 850)
# num1           NaN
# num2           NaN
# num3           NaN
# num4           NaN
# num5    885.514924
# dtype: float64

Numpy

另外使用Python的numpy(支持数组的数值计算库),可以使用numpy.apply_along_axis。并等同于 Pandas' var,相应地调整默认值 ddof

random_arry = random_df.to_numpy()

agg = np.apply_along_axis(lambda x: np.var(x, ddof=1), 0, random_arry)
print(agg)
# [828.53837793 810.75521479 820.48039962 811.72810753 885.51492378]

print(agg[agg > 850])
# [885.51492378]