有没有一个Python模块可以打开SPSS文件?

43

有没有Python模块可以打开IBM SPSS(即.sav)文件?如果有最好是最新的,不需要任何额外的dll文件/库。


可能是 Exporting to SPSS files in Python Django? 的重复问题。 如果你想要的话,这里也有一个配方在活动状态。 - Bakuriu
嗨,Bakuriu。这不是重复的问题,因为我没有引用Django框架,我谈论的是打开文件,而不是导出/写入文件,并且我提到了对某些最近的东西的偏好,这些东西不需要外部库/dll文件。这些问题有一些共同点,但它们可以引出不同的,以及相似的回答。感谢您提供的链接,但如果可能的话,我想避免使用dll文件。 - Lamps1829
另一个答案引用了Django,但实际上与此无关。由于导出需要写文件的能力,因此您也可以高度可能地读取它。通过阅读,我强烈认为您只有一个选择:使用IBM发布的.dll。我找不到任何有关该文件格式的开放规范,这意味着读取这些文件的唯一方法是使用IBM的库。您始终可以尝试反向工程格式,但这需要更多的时间和精力。 - Bakuriu
1
谢谢,Bakuriu。很不幸,但正如你所说,看起来IBM的.dll发布是要使用的东西。 - Lamps1829
10个回答

41

我发布了一个名为“pyreadstat”的Python包,它可以读取SPSS(sav、zsav和por)、Stata和SAS文件。它是围绕C库ReadStat包装的,因此非常快速。 ReadStat是R库Haven后端使用的库,该库被广泛使用且非常稳健。

该软件包是自包含的。它不需要使用R(无需安装额外的应用程序),也不依赖于IBM dll或其他外部库。

例如,要读取SPSS sav文件,您可以执行以下操作:

import pyreadstat

df, meta = pyreadstat.read_sav("/path/to/sav/file.sav")

df 是一个 pandas 的数据帧。Meta 包含元数据,例如变量标签或值标签。 read_sav 读取 sav 和 zsav(压缩)文件。还有一个 read_por 函数用于旧的 por(便携式)文件。

您可以在这里找到它:https://github.com/Roche/pyreadstat


这就是我喜欢Python的原因。在很多地方都尝试过后,最终决定使用Python。而且第一次就成功了。谢谢。 - mradul dubey
这个库的性能非常棒!非常感谢。 - Martin Bucher
我来晚了,但我想发表一下我的意见。对我来说,我正在远程服务器上工作,有时在尝试pip安装新软件包等操作时会出现问题,因此在scipy.io中有一个名为readsav的函数适用于我,并且已经包含在内。另一个使用pandas.rpy.common的最佳答案对我也不起作用,因为显然这不是rpy包含的属性。 - Steven Thomas
@StevenThomas 注意,scipy.io.readsav 读取的是 IDL sav 文件,而不是 SPSS sav 文件(本主题的话题)。IDL 是完全不同的编程环境。Pyreadstat 只能读取 SPSS 文件,无法读取 IDL 文件。 - Otto Fajardo
@OttoFajardo 谢谢您的澄清,我没有意识到有不同类型的.sav文件。也许我应该删除我的评论? - Steven Thomas
很多人对此感到困惑,所以让我们留下注释,我会这么说。 - Otto Fajardo

14
当您拥有版本号为 pandas >= 0.25.0 的 pandas 时,现在您可以只需执行 pd.read_spss()
# you need pandas >= 0.25.0 for this    
import pandas as pd
df = pd.read_spss('your_spss_file.sav')

这个库需要pyreadstat作为前提条件,所以您可能需要先安装它:

pip install pyreadstat

pd.read_spss()函数的参数详解:

参数
----------
path:字符串或路径类型
文件路径

usecols:类似列表的对象,可选参数
返回子集列。如果为None,则返回所有列。

convert_categoricals:布尔值,默认为True
转换分类列为pd.Categorical类型。

返回值
-------
DataFrame


11

根据你想做的事情——使用rpy2中的R相关命令来处理数据,或者切换到Python——有一个相关主题上由@Spacedman提供的解决方案可能很容易地适应你的需求。

否则,Pandas包括一个方便的rpy2封装器。这里是一个与Peat和Barton的weights.sav数据集一起使用的示例:

>>> import pandas.rpy.common as com
>>> filename = "weights.sav"
>>> w = com.robj.r('foreign::read.spss("%s", to.data.frame=TRUE)' % filename)
>>> w = com.convert_robj(w)
>>> w.head()
     ID  WEIGHT  LENGTH  HEADC  GENDER  EDUCATIO              PARITY
1  L001    3.95    55.5   37.5  Female  tertiary  3 or more siblings
2  L003    4.63    57.0   38.5  Female  tertiary           Singleton
3  L004    4.75    56.0   38.5    Male    year12          2 siblings
4  L005    3.92    56.0   39.0    Male  tertiary         One sibling
5  L006    4.56    55.0   39.5    Male    year10          2 siblings

9
作为后来者(比如我)的一个提示: pandas.rpy在最新的pandas版本(>0.16)中已被弃用,如这里所述。该页面包括有关更新代码以使用rpy2接口的信息。

3
感谢分享。因此,应该将com.convert_robj(rdf)替换为pandas2ri.ri2py(rdf)。但是com.robj.r('foreign::read.spss("%s", to.data.frame=TRUE)' % filename)怎么办? - Pyderman

3

但使用IBM库的好处在于,它们可以正确处理这种相当复杂的二进制文件格式。它们是免费的,使您免于为此格式编写代码的负担,并且许可证允许您重新分发它们。还有什么更好的要求呢?


1
我想要ARM支持 :) - qdot
我们在哪里可以找到IBM的库? - Tagar
您可以通过访问IBM预测分析社区网站(https://developer.ibm.com/predictiveanalytics/)上的“下载”链接来获取它们。 - JKP

3

2

我和@Pyderman有同样的问题,关于如何更新这个pandas版本(>0.16)。以下是我的解决方案:

from rpy2.robjects import pandas2ri, r
filename = 'weights.sav'
w = r('foreign::read.spss("%s", to.data.frame=TRUE)' % filename)
df = pandas2ri.ri2py(w)
df.head()

1

谢谢,SM,但是那个模块需要一个额外的dll文件,而这正是我想避免的。有没有一个模块(最好是最近的一个),它包含了所有必要的功能,而不需要使用外部库? - Lamps1829
抱歉,我不知道任何你所说的或者在谷歌上找到的外部库。为什么使用外部库是你无法忍受的事情呢?我想你每天都会使用很多外部库,无论是Python还是其他任何东西,包括操作系统。 - SpankMe
如果其他选项用尽了,我不会排除使用dll的可能性,但如果可能的话,我想避免使用它。依赖越少,事情就越简洁,出错的机会也就越小。 - Lamps1829
1
而最不可能正确的是Lamps1829。IBM为SPSS Statistics运行的所有平台免费提供的I/O模块使用与Statistics本身相同的代码,因此它们保证同步。上面提到的Python读写工具也使用这些库。随着新功能添加到sav文件格式中,这些库也会得到更新。据我所知,R库并没有完全做到这一点。 - JKP

0
你可以使用Python接口到R,然后在library(foreign)中使用read.spss导入数据。

0
from scipy.io import readsav

import pandas as pd

sav_df = readsav('file.sav')

df=pd.DataFrame(sav_df)

4
虽然这段代码可能解决了问题,但是包括解释它如何以及为什么解决了问题将有助于提高您的帖子质量,并可能导致更多的赞。请记住,您正在回答未来读者的问题,而不仅仅是现在提问的人。请[编辑]您的答案以添加解释并指出适用的限制和假设。 - jmoerdyk
4
虽然这段代码可能解决了问题,但是包括解释这段代码如何解决问题以及为什么能解决问题,将会极大地提高你的帖子质量,并可能获得更多的赞同。请记住,你的回答是为了未来的读者,而不仅仅是现在提问的人。请[编辑]你的回答,添加解释并说明适用的限制和假设。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接