【问题标题】:Divide and Conquer Lists in Python (to read sav files using pyreadstat)Python 中的分而治之列表(使用 pyreadstat 读取 sav 文件)
【发布时间】:2020-12-05 15:08:39
【问题描述】:

我正在尝试在 python 中使用 pyreadstat 读取 sav 文件,但在一些罕见的情况下,由于字符串变量具有特殊字符,我收到了 UnicodeDecodeError 错误。

为了处理这个问题,我认为我不会加载整个变量集,而是只加载没有此错误的变量。

以下是我随身携带的伪代码。这不是一个非常有效的代码,因为我使用 try 和 except 检查列表的每个项目中的错误。

# Reads only the medata to get information about the variables
df, meta = pyreadstat.read_sav('Test.sav', metadataonly=True)
list = meta.column_names # All variables are stored in list
result = []
for var in list:
    print(var)
    try:
        df, meta = pyreadstat.read_sav('Test.sav', usecols=[str(var)]) 
        # If no error that means we can store this variable in result
        result.append(var)
    except:
        pass
# This will finally load the sav for non error variables
df, meta = pyreadstat.read_sav('Test.sav', usecols=result) 

对于包含 1000 多个变量的 sav 文件,处理它需要很长时间。 我在想是否有一种方法可以使用分而治之的方法并更快地做到这一点。以下是我建议的方法,但我在实现递归算法方面不是很好。有人可以帮我用伪代码吗,这将非常有帮助。

  1. 获取列表并尝试读取 sav 文件
  2. 如果没有错误,则可以将输出存储在结果中,然后我们读取 sav 文件
  3. 如果出现错误,则将列表分成两部分并再次运行它们......
  4. 第 3 步需要再次运行,直到我们得到一个没有给出任何错误的列表

使用第二种方法,我 90% 的 sav 文件将在第一遍时加载,因此我认为递归是一个好方法

您可以尝试重现 sav 文件 here 的问题

【问题讨论】:

  • 将任何对象添加到列表中应该没有错误。你肯定又迈出了一步。为什么不识别导致问题的对象类型并以这种方式处理它们。或者更好的是,在错误有机会提出之前找出错误的原因。
  • 为什么不分享你正在做的操作,以便我们可以看到问题所在。
  • 另外,我认为您的第二种方法比第一种方法效率低,因为您必须多次执行许多计算。
  • list.append(i) 应该没有单一的问题,它会追加它找到的任何内容。可能您遇到的问题是读取数据时,是txt还是csv?
  • 在 python 中使用递归不会为您的情况增加任何好处。迭代“通常”更快。此外,在 python 中使用递归时,总是有可能遇到堆栈限制错误。也许您可以考虑多线程或多处理方法。

标签: python arrays list spss divide-and-conquer


【解决方案1】:

对于这种特定情况,我建议采用不同的方法:您可以为 pyreadstat.read_sav 提供一个参数“encoding”以手动设置编码。如果您不知道它是哪一种,您可以在此处遍历编码列表:https://gist.github.com/hakre/4188459 以找出哪一种有意义。例如:

# here codes is a list with all the encodings in the link mentioned before
for c in codes:
    try:
        df, meta = p.read_sav("Test.sav", encoding=c)
        print(encoding)
        print(df.head())
    except:
        pass

我做了,假设字符串是非拉丁字母表,有一些可能有意义。然而,最有希望的不在列表中: encoding="UTF8" (列表包含 UTF-8,带有破折号并且失败)。使用 UTF8(没有破折号)我得到了这个:

నేను గతంలో వాడిన బ

根据谷歌翻译,在泰卢固语中的意思是“我曾经来过 b”。不确定这是否完全有道理,但这是一种方式。

这种方法的优点是,如果您找到正确的编码,您将不会丢失数据,并且读取数据会很快。缺点是你可能找不到正确的编码。

如果您找不到正确的编码,无论如何您都会非常快速地读取有问题的列,您可以稍后在 pandas 中通过检查哪些字符列不包含拉丁字符来丢弃它们。这将比您建议的算法快得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-20
    • 2020-12-16
    • 2013-11-09
    • 1970-01-01
    • 1970-01-01
    • 2020-09-21
    • 2021-07-12
    相关资源
    最近更新 更多