数据STUDIO

Python数据处理基础题:标注数据整理

©️数据STUDIO转载|作者: 小小明-代码实体 来源:https://xxmdmst.blog.csdn.net/

需求

背景:

有一张图片, 其上用矩形框标注出数目不定的若干对象. 每个对象有若干属性, 每个属性值为预定的值之一. 要求解析输入数据, 适配成人和程序方便阅读的csv格式, 打印或保存结果.

输入:

输入数据有两个, assignment描述的是标注需求, annotations描述的是标注结果.

输入数据示例如下:

assignment_sample = {            # assignment 顶层为python字典    'type': 'rectangle',         # 标注对象工具类型, 题目中只有矩形框一种, 可忽略    'properties': [{             # 要求标注对象的属性. 数组, 其中每个字典描述一个属性, 数目不定        'id': 1,                 # 此属性项的唯一id        'name': '对象类型',      # 此属性项的名称        'items': ['行人', '车'], # 属性值备选项. 对应annotations中的属性值为其中之一.    }],}annotations_sample = [{          # 标注结果, 数组, 其中每个元素描述一个标注对象. 图里画了多少框, 就有多少个    'object_id': 1,              # 一张图中标注对象的唯一id    'rectangle': {               # 题目只有矩形框        'x1': 100,               # 框的坐标, 整数. (x1, y1)是框的左上角点, (x2, y2)是框的右下角点. (图片左上角坐标为(0, 0))        'y1': 10,        'x2': 201,        'y2': 250,    },    'properties': [{             # 每项表示一个属性. 每个属性一定有值, 所以其长度等于assignment中properties的长度         'property_id': 1,        # 对应assignment['properties']中的'id', 表示此项是哪个属性项.         'value': '行人',         # 标注的属性值    }]}]

输出:

csv格式, 每行代表一个对象, 要求输出每个对象的object_id和属性值,第一行为列头, 第一个字段是object_id, 余下每个字段是每个属性的name (如示例中的"对象类型")

下面每个对象顺序无要求, object_id对应正确即可,直接print出结果或保存为文件均可。

上面简单示例的输出结果应为:

object\_id,对象类型  1,行人

提示: 用python自带的csv.DictWriter. 可参考官方文档: https://docs.python.org/3/library/csv.html (用手动拼接字符串的方式生成结构化数据是巨大的减分项)

进阶需求, 可任选:

1. 输出结果中添加一个字段, 表示框的面积,例如:

object_id,对象类型,面积1,行人,3000

2. 额外打印出每个"对象类型"的框的个数统计, 格式任意,例如:

object_id,对象类型,面积,个数1,行人,3000,1

数据工程师测试题.py 中待完整的代码:

def convert_to_csv(assignment, annotations):    # 请补全此函数    raise NotImplementedError# 程序从这里开始执行if __name__ == '__main__':    # 输入数据不要改    assignment = {        'type': 'rectangle',        'properties': [{            'id': 1,            'name': '对象类型',            'items': ['小汽车', '大汽车', '人', '自行车'],        }, {            'id': 2,            'name': '是否清晰',            'items': ['是', '否'],        }, {            'id': 3,            'name': '是否完整',            'items': ['完整', '不完整'],        }],    }    annotations = [{        'object_id': 100,        'rectangle': {            'x1': 100,            'y1': 100,            'x2': 150,            'y2': 150,        },        'properties': [{            'property_id': 1,            'value': '自行车',        }, {            'property_id': 2,            'value': '是',        }, {            'property_id': 3,            'value': '完整',        }]    }, {        'object_id': 101,        'rectangle': {            'x1': 200,            'y1': 100,            'x2': 450,            'y2': 150,        },        'properties': [{            'property_id': 1,            'value': '大汽车',        }, {            'property_id': 2,            'value': '是',        }, {            'property_id': 3,            'value': '不完整',        }]    }, {        'object_id': 102,        'rectangle': {            'x1': 100,            'y1': 150,            'x2': 120,            'y2': 150,        },        'properties': [{            'property_id': 3,            'value': '完整',        }, {            'property_id': 1,            'value': '大汽车',        }, {            'property_id': 2,            'value': '否',        }]    }, {        'object_id': 103,        'rectangle': {            'x1': 300,            'y1': 100,            'x2': 400,            'y2': 200,        },        'properties': [{            'property_id': 3,            'value': '完整',        }, {            'property_id': 1,            'value': '人',        }, {            'property_id': 2,            'value': '是',        }]    }]    convert_to_csv(assignment, annotations)

解题

实现函数为:

from collections import Counterimport csvfrom io import StringIOdef convert_to_csv(assignment, annotations):    # 请补全此函数    properties = {row["id"]: row["name"] for row in assignment["properties"]}    data = []    c = Counter()    for annotation in annotations:        row = {"object_id": annotation["object_id"]}        for propertie in annotation["properties"]:            row[properties[propertie["property_id"]]] = propertie["value"]        p = annotation["rectangle"]        row["面积"] = (p["x2"]-p["x1"])*(p["y2"]-p["y1"])        c[row["对象类型"]] += 1        data.append(row)    for row in data:        row["个数"] = c[row["对象类型"]]    csvfile = StringIO()    writer = csv.DictWriter(csvfile, fieldnames=data[0].keys())    writer.writeheader()    for row in data:        writer.writerow(row)    csvfile.seek(0)    print(csvfile.read())

结果

object_id,对象类型,是否清晰,是否完整,面积,个数 100,自行车,是,完整,2500,1 101,大汽车,是,不完整,12500,2 102,大汽车,否,完整,0,2 103,人,是,完整,10000,1

🏴‍☠️宝藏级🏴‍☠️ 原创公众号『 数据STUDIO 』内容超级硬核。公众号以Python为核心语言,垂直于数据科学领域,包括 可戳 👉 Python | MySQL | 数据分析 | 数据可视化 | 机器学习与数据挖掘 | 爬虫 等,从入门到进阶!

长按👇关注- 数据STUDIO -设为星标,干货速递