将.sav文件转换为pandas数据框架

4

我正在编写一个数据检查程序,用于审查spss文件,并需要以编程方式处理不同的检查。第一步是访问一个spss文件,将其转换为pandas dataframe,并从那里运行我的检查。我发现唯一可行的方法是通过RPY2来完成。不幸的是,我很少了解R语言,并且无法使下面两个解决方案生效。任何帮助/文献都将不胜感激。

我从其他帖子中提取了一些内容并创建了以下代码:

使用RPY2

from rpy2.robjects import pandas2ri
from rpy2.robjects import r
from pathlib import Path
import pyreadstat
pandas2ri.activate()

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

错误:

rpy2.rinterface_lib.embedded.RRuntimeError: Error in foreign::read.spss("path to test.sav",  : 
  error reading system-file header

使用pyreadstat(这让我得到了列,但是当我尝试获取基础数据时出现错误)

    meta = pyreadstat.read_sav(filename, metadataonly=True)
    cols = [x for x in meta[0]]
    df, meta = pyreadstat.read_sav(filename, usecols=cols)
    print(df)

错误:

pyreadstat._readstat_parser.PyreadstatError: STRING type with value 4/23/19 17:50 with date type

更新:

现在使用 haven 但仍然出现错误:

rdf = r(f'haven::read_sav("{filename}")')

错误:

ValueError: 无效值 NaN(不是一个数字)


请在 Github 存储库中提交一个带有示例文件的问题,以获取 pyreadstat 的支持。您所描述的格式错误已知,并且只需要一个示例文件让 C 库学习如何正确解析它们。 - Otto Fajardo
4个回答

3
我使用pyreadstat完成了它,这是你的第二个选项:
df, metadata = pyreadstat.read_sav("path to file", metadataonly=True)

这会返回一个空的数据框(只有列名)和所有元数据。 使用metadata.variable_value_labels可以获得变量值的字典。

df, metadata = pyreadstat.read_sav("path to file", apply_value_formats=True) 

这将返回所有值已经替换的DF。

这可能有帮助:https://ofajardo.github.io/pyreadstat_documentation/_build/html/index.html


3

在DiegoC的回答基础上进行改进/更新,如果你已经安装了pyreadstat,可以使用pd.read_spss。所以,这很容易:

df = pd.read_spss("path_to_sav_file.sav")

如果出现错误提示让你安装pyreadstat,那么你需要用它来使用pd.read_spss。对于超级新手:

$ pip install pyreadstat

或者
$ conda install pyreadstat

2
相反,您可以使用scipy.io.readsav库将.sav文件转换为字典。最初的回答。
scipy.io.readsav(file_name, idict=None, python_dict=False,
 uncompressed_file_name=None, verbose=False)

然后,这个字典可以很容易地转换成pandas数据框。
最初的回答已经被翻译成了上述内容。

1
scipy.io.readsav 用于读取IDL文件,而不是SPSS文件。 - Otto Fajardo

2
我会使用SavReaderWriter包:最初的回答。
pip install savReaderWriter --upgrade

import pandas
import savReaderWriter

with savReaderWriter.SavReader('mydata.sav', ioUtf8 = True) as reader:
    df = pandas.DataFrame(reader.all(), columns = [s.decode('CP1252') for s in reader.header])
df.head()

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