TranslateProject/published/201610/team_test/part 4 - Building a data science portfolio - Machine learning project.md
2016-11-01 11:57:58 +08:00

5.0 KiB
Raw Permalink Blame History

计算运用数据中的值

接下来我们会计算过程数据或运用数据中的值。我们要做的就是推测这些数据代表的贷款是否被收回。如果能够计算出来,我们只要看一下包含贷款的运用数据的参数 foreclosure_date 就可以了。如果这个参数的值是 None 那么这些贷款肯定没有收回。为了避免我们的样例中存在少量的运用数据我们会计算出运用数据中有贷款数据的行的行数。这样我们就能够从我们的训练数据中筛选出贷款数据排除了一些运用数据。

下面是一种区分贷款数据和运用数据的方法:

在上面的表格中,采集数据中的每一行数据都与运用数据中的多行数据有联系。在运用数据中,在收回贷款的时候 foreclosure_date 就会以季度的的形式显示出收回时间,而且它会在该行数据的最前面显示一个空格。一些贷款没有收回,所以与运用数据中的贷款数据有关的行都会在前面出现一个表示 foreclosure_date 的空格。

我们需要计算 foreclosure_status 的值,它的值是布尔类型,可以表示一个特殊的贷款数据 id 是否被收回过,还有一个参数 performance_count ,它记录了运用数据中每个贷款 id 出现的行数。 

计算这些行数有多种不同的方法:

  • 我们能够读取所有的运用数据,然后我们用 Pandas 的 groupby 方法在数据框中计算出与每个贷款 id 有关的行的行数,然后就可以查看贷款 id 的 foreclosure_date 值是否为 None 。     - 这种方法的优点是从语法上来说容易执行。     - 它的缺点需要读取所有的 129236094 行数据,这样就会占用大量内存,并且运行起来极慢。
  • 我们可以读取所有的运用数据,然后使用采集到的数据框去计算每个贷款 id 出现的次数。     - 这种方法的优点是容易理解。     - 缺点是需要读取所有的 129236094 行数据。这样会占用大量内存,并且运行起来极慢。
  • 我们可以在迭代访问运用数据中的每一行数据,而且会建立一个区分开的计数字典。
    • 这种方法的优点是数据不需要被加载到内存中,所以运行起来会很快且不需要占用内存。     - 缺点是这样的话理解和执行上可能有点耗费时间,我们需要对每一行数据进行语法分析。

加载所有的数据会非常耗费内存,所以我们采用第三种方法。我们要做的就是迭代运用数据中的每一行数据,然后为每一个贷款 id 生成一个字典值。在这个字典中,我们会计算出贷款 id 在运用数据中出现的次数,而且如果 foreclosure_date 不是 Nnoe 。我们可以查看 foreclosure_status 和 performance_count 的值 。

我们会新建一个 annotate.py 文件,文件中的代码可以计算这些值。我们会使用下面的代码:

  • 导入需要的库
  • 定义一个函数 count_performance_rows 。
    • 打开 processed/Performance.txt 文件。这不是在内存中读取文件而是打开了一个文件标识符,这个标识符可以用来以行为单位读取文件。 
    • 迭代文件的每一行数据。
    • 使用分隔符(|)分开每行的不同数据。
    • 检查 loan_id 是否在计数字典中。
      • 如果不存在,进行一次计数。
    • loan_id 的 performance_count 参数自增 1 次,因为我们这次迭代也包含其中。
    • 如果日期是 None 我们就会知道贷款被收回了然后为foreclosure_status 设置合适的值。
import os
import settings
import pandas as pd

def count_performance_rows():
    counts = {}
    with open(os.path.join(settings.PROCESSED_DIR, "Performance.txt"), 'r') as f:
        for i, line in enumerate(f):
            if i == 0:
                # Skip header row
                continue
            loan_id, date = line.split("|")
            loan_id = int(loan_id)
            if loan_id not in counts:
                counts[loan_id] = {
                    "foreclosure_status": False,
                    "performance_count": 0
                }
            counts[loan_id]["performance_count"] += 1
            if len(date.strip()) > 0:
                counts[loan_id]["foreclosure_status"] = True
    return counts

获取值

只要我们创建了计数字典,我们就可以使用一个函数通过一个 loan_id 和一个 key 从字典中提取到需要的参数的值:

def get_performance_summary_value(loan_id, key, counts):
    value = counts.get(loan_id, {
        "foreclosure_status": False,
        "performance_count": 0
    })
    return value[key]

上面的函数会从计数字典中返回合适的值,我们也能够为采集数据中的每一行赋一个 foreclosure_status 值和一个 performance_count 值。如果键不存在,字典的 [get][33] 方法会返回一个默认值,所以在字典中不存在键的时候我们就可以得到一个可知的默认值。