为何不同环境下用scipy计算Pandas DataFrame的Z-Score返回类型不同?
为何scipy.stats.zscore处理Pandas DataFrame时返回类型存在差异?
我尝试使用scipy的zscore方法计算Pandas DataFrame的Z-Score,计算成功但在不同主机运行时返回的类型不同,推测与相关软件包版本差异有关,但尚未找到原因。
两个主机的环境配置如下:
| Host 1 | Host2 |
|---|---|
| python 3.6.8 | python 3.7.3 |
| pandas 1.1.5 | pandas 1.3.1 |
| numpy 1.19.5 | numpy 1.19.2 |
| scipy 1.5.4 | scipy 1.7.3 |
运行示例
Host 1
import numpy as np import pandas as pd from scipy.stats import zscore df = pd.DataFrame(np.random.randint(100, 200, size=(5, 3)), columns=['A', 'B', 'C']) # -------------------------------- In [5]: df Out[5]: A B C 0 166 135 141 1 156 110 167 2 104 159 114 3 150 156 157 4 163 113 180 In [10]: zscore(df) Out[10]: array([[ 0.80546745, 0.01940194, -0.47372066], [ 0.36290292, -1.19321913, 0.66671797], [-1.93843265, 1.18351816, -1.65802232], [ 0.0973642 , 1.03800363, 0.22808773], [ 0.67269809, -1.0477046 , 1.23693729]]) In [11]: zscore(df, ddof=0) Out[11]: array([[ 0.80546745, 0.01940194, -0.47372066], [ 0.36290292, -1.19321913, 0.66671797], [-1.93843265, 1.18351816, -1.65802232], [ 0.0973642 , 1.03800363, 0.22808773], [ 0.67269809, -1.0477046 , 1.23693729]]) In [12]: type(zscore(df)) Out[12]: numpy.ndarray
Host 2
import numpy as np import pandas as pd from scipy.stats import zscore df = pd.DataFrame(np.random.randint(100, 200, size=(5, 3)), columns=['A', 'B', 'C']) # -------------------------------- In [77]: df Out[77]: A B C 0 151 188 190 1 195 199 103 2 130 174 188 3 168 194 146 4 171 138 129 In [78]: zscore(df) Out[78]: A B C 0 -0.553990 0.428052 1.148875 1 1.477308 0.928963 -1.427210 2 -1.523474 -0.209472 1.089654 3 0.230829 0.701276 -0.153973 4 0.369327 -1.848819 -0.657346 In [79]: zscore(df, ddof=0) Out[79]: A B C 0 -0.553990 0.428052 1.148875 1 1.477308 0.928963 -1.427210 2 -1.523474 -0.209472 1.089654 3 0.230829 0.701276 -0.153973 4 0.369327 -1.848819 -0.657346 In [80]: type(zscore(df)) Out[80]: pandas.core.frame.DataFrame
原因分析
这个差异是Scipy版本更新带来的行为变化:
- 在Scipy 1.7.0及以后的版本中,
scipy.stats.zscore新增了对Pandas DataFrame/Series的原生支持,处理这类输入时会保留原数据结构,返回同类型的Pandas对象。 - 而Scipy 1.5.x版本中,
zscore会先将DataFrame转换为Numpy数组进行计算,最终返回Numpy ndarray类型。
你的Host1使用Scipy 1.5.4,属于旧版本;Host2使用Scipy 1.7.3,是更新后的版本,这就是返回类型不同的核心原因。
补充说明:
- 如果需要在新版本中强制返回Numpy数组,可以手动将DataFrame转为数组后传入,比如
zscore(df.values); - 如果在旧版本中想要保留DataFrame结构,可以将计算结果重新包装成DataFrame:
pd.DataFrame(zscore(df), columns=df.columns)。
内容的提问来源于stack exchange,提问作者MrBlueberry
相关产品推荐
相关产品推荐

