【问题标题】:How to clean data without pandas or numpy?如何在没有 pandas 或 numpy 的情况下清理数据?
【发布时间】:2021-02-15 08:48:48
【问题描述】:

我必须使用 python 来清理数据以便于分析,但是在这种情况下我不能使用 pandas 要求和期望如下:

actual = preprocess([
            ('Survived', 'Pclass', 'Name', 'Gender', 'Age', 'Fare'),
            ('no', '3', 'Braund Mr. Owen Harris', 'male', '22', '7.25'),
            ('Dead', '3', 'Braund Ms. Maria', 'Female', '21', ''),
            ('Yes', '1', 'Cumings Mrs. John Bradley (Florence Briggs Thayer)', 'F', '38', '71.28'),
            ('', '3', 'Vander Planke Miss. Augusta', 'female', '', ''),
            ('Dead', '4', 'Lennon Mr. Denis', 'male', '13', '15.5')])

expected = (
                ('Survived', 'Pclass', 'Name', 'Gender', 'Age', 'Fare'),
                [
                    (False, 3, 'Braund Mr. Owen Harris', 'male', 22.0, 7.25),
                    (False, 3, 'Braund Ms. Maria', 'female', 21.0, 25.0),
                    (True, 1, 'Cumings Mrs. John Bradley (Florence Briggs Thayer)', 'female', 38.0, 71.28),
                    ('', 3, 'Vander Planke Miss. Augusta', 'female', '', 25.0), 
                    (False, 4, 'Lennon Mr. Denis', 'male', 13.0, 15.5)]
                ]
           )

你能在这种情况下给一些建议吗?

【问题讨论】:

  • 信息不足。为什么第 4 和第 5 条数据线没有包含在预期输出中?将第一列转换为布尔值的规则是什么?等等……
  • 抱歉,我可能错过了最后一行。规则是:(1) Survived - boolean,(2) Plass - int,(3) Name - string,(4) Gender - string(仅限男性和女性),(5) age - float,(6) fare -浮动
  • 我可以确定第一列将被转换为布尔值。我要问的是您将字符串更改为 True 或 False 的规则。顺便说一句,您的预期输出中缺少两行,而不是一行。
  • True 为 Yes,错误为 no/dead。 ('', 3, 'Vander Planke Miss. Augusta', 'female', '', 25.0), (False, 4, 'Lennon Mr. Denis', 'male', 13.0, 15.5)])
  • 缺失值替换的规则是什么?在您的示例中,缺少的“票价”已替换为“25.0”。这是一般规则吗?缺少年龄或缺少“幸存”状态是怎么回事?

标签: python csv data-cleaning


【解决方案1】:

缺少某些信息(例如,如何处理缺失值?或者是否应该过滤掉不完整的条目?是否需要对结果进行排序?),但我还是会尝试回答:

要实现转换元组“列”的类型和/或内容的预期结果,您需要将旧值映射和/或类型转换为新值。


映射字符串

您可以采用不同的方法将不同的输入值映射到一系列输出值。我将在我的回答中使用两个:(1) if ... else 语句和 (2) 执行 switch ... case 语句的 python 方式。

为了从“Survived”的不同可能条目中获取bool 值,我使用了方法 (2)。为此,您使用映射设置字典,然后从中为每个候选人获取适当的条目(请参阅Replacements for switch statement in Python?)。您可以将其与字符串 lower() 函数结合使用,这样您就可以忽略大小写 (How do I lowercase a string in Python?)。您还可以添加一个默认值,以防在字典中找不到密钥时使用,在下面的示例中,我使用None

例子:

entry = 'NO'

switcher_survived = {
    'no': False,
    'dead': False,
    'yes': True
}

result = switcher_survived.get(entry.lower(), None)

同样的方法可以根据不同的输入可能性来设置性别。


类型转换

对于数字,您可以简单地将它们转换为所需的类型。但是,这仅在字符串包含可以成功转换的数字时才有效。请注意,在您的示例中,您有一个带有空字符串的条目,当您尝试投射时,这将导致 ValueError 。所以你需要检查一下,并可能再次希望默认为某个值。我使用nan = float('NaN'),因为这是在不使用其他包的情况下维护正确类型的好方法(请参阅Assigning a variable NaN in python without numpy)。

例子:

nan = float('NaN') 

entry = '2.5'

result = (float(entry) if float(entry) != "" else nan)

我在这里使用单行 if-then-else 语句(请参阅 Putting a simple if-then-else statement on one line),因为这有利于最后的完整示例。


放在一起

actual = [
        ('Survived', 'Pclass', 'Name', 'Gender', 'Age', 'Fare'),
        ('no', '3', 'Braund Mr. Owen Harris', 'male', '22', '7.25'),
        ('Dead', '3', 'Braund Ms. Maria', 'Female', '21', ''),
        ('Yes', '1', 'Cumings Mrs. John Bradley (Florence Briggs Thayer)', 'F', '38', '71.28'),
        ('', '3', 'Vander Planke Miss. Augusta', 'female', '', ''),
        ('Dead', '4', 'Lennon Mr. Denis', 'male', '13', '15.5')]


nan = float('NaN')

switcher_survived = {
    'no': False,
    'dead': False,
    'yes': True
}

switcher_gender = {
    'male': 'male',
    'm': 'male',
    'female': 'female',
    'f': 'female'
}

def process(lst):
    result = []
    current = 1
    while current < len(lst):
        tuple = (switcher_survived.get(lst[current][0].lower(),''),
                 int(lst[current][1]),
                 lst[current][2],
                 switcher_gender.get(lst[current][3].lower(),''),
                 (float(lst[current][4]) if lst[current][4] != "" else ''),
                 (float(lst[current][5]) if lst[current][5] != "" else 25.0)
                )
        result.append(tuple)
        current += 1
    return [lst[0], result]

expected = process(actual)

print(expected)

一些备注:

  • 在最后一个示例中,我已将“票价”列的默认值更改为 25.0,以符合您的预期结果。

  • 出于同样的原因,我还将“Survived”、“Gender”和“Age”的默认值更改为空字符串'',而不是None,分别为NaN。请注意,这违反了您自己的要求,因为空字符串显然不是boolfloat 类型。当您稍后处理数据时,这可能会产生影响。特别是,“Survived”列中的空字符串可能会被静默评估为False

  • 要过滤掉不完整的数据,您可以将默认值改回NoneNaN,并且只将完整的行添加到最终数据集中。为此,您可以检查任何元组的字段是否为None(请参阅What is the best way to check if a tuple has any empty/None values in Python?):

         if not any(map(lambda x: (x is None) or (x is nan), tuple)):
             result.append(tuple)
    
  • 如果您想按任意列对列表进行排序,可以在返回结果之前使用 lambda 函数作为排序键(请参阅Syntax behind sorted(key=lambda: ...))。例如。按名称排序:

     result = sorted(result, key=lambda tuple: tuple[2])
    

【讨论】:

    猜你喜欢
    • 2021-03-16
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-31
    • 2021-12-24
    • 2014-10-19
    • 2011-03-27
    相关资源
    最近更新 更多