将数组转换为真/假矩阵

数据挖掘 scikit-学习 熊猫 矩阵
2022-02-23 03:04:49

我有一个数据集,其中每条记录都是一个带有标签的 json 文档和一组信号。每条记录的信号都会有所不同:

{
    "label":"bad",
    "id": "0009",
    "signals":["high_debt_ratio", "no_job"] 
},

{
    "label":"good",
     "id": "0002",
    "signals":["high_debt_ratio", "great_credit", "no_id_match"] 
},

{
    "label":"good",
    "id": "0003",
    "signals":["low_debt_ratio", "great_credit"] 
},

{
    "label":"bad",
    "id": "0001",
    "signals":["high_risk_loc", high_debt_ratio", "no_job", "no_id_match"] 
}

我想将其转换为如下所示的矩阵:

ID 标签 high_risk_loc 高负债率 没工作 伟大的信用 no_id_match 低债务比率
0009 坏的 错误的 真的 真的 错误的 错误的 错误的
0002 好的 错误的 真的 错误的 真的 真的 错误的
0003 好的 错误的 错误的 错误的 真的 错误的 真的
0001 坏的 真的 真的 真的 错误的 真的 错误的

我创建了一个函数,但这似乎是一件很常见的事情。是否有一个 python 库(pandas、scikit 等)可以为您执行此操作?我宁愿使用包装中的东西,但我不确定要搜索什么。

3个回答

首先,您需要使用json_normalize在数据框中读取您的 json 数据pandas

import pandas as pd

df = pd.json_normalize(['your json data'])

您的数据框看起来像这样

  label    id                                            signals
0   bad  0009                          [high_debt_ratio, no_job]
1  good  0002       [high_debt_ratio, great_credit, no_id_match]
2  good  0003                     [low_debt_ratio, great_credit]
3   bad  0001  [high_risk_loc, high_debt_ratio, no_job, no_id...

现在我们需要列的唯一值列表signals并以其可用性循环并基于需要插入特定列的值TrueFalse在特定列的值中......signals在获得最终数据后也删除了列

for i in list(set(df.signals.sum())):
    df[i] = df.signals.apply(lambda x: i in x)
df.drop('signals',axis=1,inplace=True)
print(df)
-:output:-
  label    id  low_debt_ratio  great_credit  high_debt_ratio  no_id_match  high_risk_loc  no_job
0   bad  0009           False         False             True        False          False    True
1  good  0002           False          True             True         True          False   False
2  good  0003            True          True            False        False          False   False
3   bad  0001           False         False             True         True           True    True

你可以试试这个单行解决方案:

d = pd.json_normalize([{
    "label":"bad",
    "id": "0009",
    "signals":["high_debt_ratio", "no_job"] 
},

{
    "label":"good",
     "id": "0002",
    "signals":["high_debt_ratio", "great_credit", "no_id_match"] 
},

{
    "label":"good",
    "id": "0003",
    "signals":["low_debt_ratio", "great_credit"] 
},

{
    "label":"bad",
    "id": "0001",
    "signals":["high_risk_loc", "high_debt_ratio", "no_job", "no_id_match"] 
}])

d.merge(d.signals.apply(lambda x: "|".join(x)).str.get_dummies(sep = "|"), left_index = True, right_index= True)

输出:

在此处输入图像描述

使用 sklearn 的一些直观的东西MultiLabelBinarizer,虽然稍微有点冗长:

from sklearn.preprocessing import MultiLabelBinarizer

mlb = MultiLabelBinarizer()
mlb.fit(df['signals'])
new_col_names = mlb.classes_

# New DataFrame containing 0/1 values of the signals
signals_df = pd.DataFrame(mlb.transform(df['signals']), columns=new_col_names)

# Concatenate with original DataFrame
pd.concat( [df, signals_df], axis=1 )