likes
comments
collection
share

零基础入门Python·数据分析先导篇——CSV/JSON互转

作者站长头像
站长
· 阅读数 54

基础操作

CSV文件的读写

示例代码

import csv
from pathlib import Path

# 检查文件是否存在,如果不存在则创建空文件
file_path = Path('data.csv')
file_path.touch(exist_ok=True)

# 读取CSV文件
with open('data.csv', 'r') as csvfile:
    reader = csv.reader(csvfile)
    for row in reader:
        print(row)

# 写入CSV文件
with open('data.csv', 'w', newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerow(['name', 'department', 'birthday month'])

csv模块

Python的csv模块是一个强大的库,用于处理CSV(逗号分隔值)文件。它是Python标准库的一部分,因此不需要安装任何额外的包就可以使用。csv模块提供了一系列功能,使得读取和写入CSV文件变得非常简单和直接。它支持各种自定义选项,包括自定义分隔符、引号处理、行结束符等,使其能够处理各种不同格式的CSV文件。

主要特性

  • 简单性:提供了简单的接口来读取和写入CSV文件。
  • 灵活性:可以处理不同的CSV方言(例如,不同的分隔符、引号规则等)。
  • 自动化:自动处理复杂的转义和引号,简化了编程工作。
读取CSV文件
  • csv.reader(csvfile, dialect='excel', **fmtparams)

    • 用于创建一个读取器对象,该对象将遍历给定的csvfile中的每一行。
    • csvfile参数应该是一个已打开的文件对象或类似文件的对象。
    • dialectfmtparams允许自定义文件的格式,如分隔符、引号规则等。
  • csv.DictReader(csvfile, fieldnames=None, restkey=None, restval=None, dialect='excel', **fmtparams)

    • 创建一个字典读取器对象,该对象将遍历csvfile中的每一行,将每行映射为一个字典。其中,字典的键由fieldnames提供。
    • 如果fieldnames参数为空,读取器会将文件的第一行视为列名。
写入CSV文件
  • csv.writer(csvfile, dialect='excel', **fmtparams)

    • 用于创建一个写入器对象,该对象提供了将数据写入csvfile的方法。
    • csvfile参数应该是一个已打开的文件对象或类似文件的对象,通常以写入模式打开。
  • csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', **fmtparams)

    • 创建一个字典写入器对象,该对象提供了将字典写入csvfile的方法。
    • fieldnames参数是一个序列,指定了输出CSV文件的列名。每个字典的键应与fieldnames中的一个条目相对应。
常用方法

对于csv.readercsv.writer对象:

  • writer.writerow(row)
    • row(一个字符串列表)写入到CSV文件中,作为一行数据。
  • writer.writerows(rows)
    • rows(一个字符串列表的列表)写入到CSV文件中,每个内部列表作为一行数据。

对于csv.DictReadercsv.DictWriter对象:

  • writer.writeheader()DictWriter特有):
    • 将列名(即fieldnames)写入CSV文件作为头行。
  • writer.writerow(rowdict)DictWriter特有):
    • rowdict(一个字典)写入CSV文件中,每个键值对应一列。
参数和方言

csv模块中的dialectfmtparams参数允许用户自定义CSV文件的解析和写入方式,以适应不同的CSV格式。这些参数可以控制如分隔符、引号规则、行结束符等方面的行为。

  • 方言(Dialect)
    • 方言是预定义的格式设置集合,如excelunix等,分别对应Excel兼容的CSV格式和Unix/Linux系统中常见的CSV格式。
  • 格式参数(Format parameters)
    • 包括delimiterquotecharescapecharquoting等,允许更细粒度地控制CSV的读写行为。

通过灵活运用这些函数、方法和参数,可以高效地处理各种CSV文件。

pathlib模块

pathlib是Python 3.4及更高版本中引入的一个库,它提供了面向对象的文件系统路径操作。pathlib旨在以一种更直观和易于理解的方式来处理文件系统路径,它将文件系统路径视为适当的对象,而不是仅仅处理字符串表示。这使得执行路径相关操作(如合并路径、获取文件的绝对路径、检查文件是否存在等)变得更加直观和安全。

主要特性

  • 面向对象:路径被封装为Path对象,提供了丰富的方法和属性来处理和查询路径。
  • 易用性:通过方法链式调用,使得代码更加清晰和简洁。
  • 跨平台:自动处理不同操作系统之间路径表示的差异,提高代码的可移植性。
  • 综合性:提供了创建文件、文件夹、读写文件、路径解析等多种功能。

结合csvpathlib模块,可以非常方便地处理CSV文件的读写操作,同时确保了代码的健壮性和可读性。pathlib提供的路径操作方法与csv模块的读写功能搭配使用,可以有效地管理和操作文件系统中的CSV文件。

JSON数据的处理

JSON包官网文档传送门

2024年05月06日12:55:28

py.v 3.12.3

示例代码

import json

# 解析JSON字符串
json_string = '{"name": "王德发", "age": 30, "city": "北京"}'
parsed_json = json.loads(json_string)
print(parsed_json['name'])

# 生成JSON字符串
person_dict = {'name': '王德发', 'age': 30, 'city': '北京'}
json_string = json.dumps(person_dict,)
print(json_string)

# 输出
# 王德发
# {"name": "\u738b\u5fb7\u53d1", "age": 30, "city": "\u5317\u4eac"}

这里的“乱码”可以看一下dumps的ensure_ascii参数

Python的json模块是标准库的一部分,提供了一套简单的方法和过程,用于编码和解码JSON(JavaScript Object Notation)数据。JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。json模块使得Python能够轻松地将Python对象层次结构转换成JSON格式的字符串,或者将JSON格式的字符串转换成Python对象。

主要特性

  • 简单易用json模块提供了直观的函数和方法,用于处理JSON数据,使得从Python程序到JSON格式的转换,以及反向转换变得非常简单。

  • 灵活性:支持几乎所有的Python基本类型和数据结构转换为JSON格式,包括列表、字典、字符串、整数、浮点数、布尔值等。

  • 可扩展:通过自定义编码器(JSONEncoder的子类)和解码器(JSONDecoder的子类),可以处理更复杂的数据类型(如日期时间等)的转换。

  • json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

    • 将Python对象编码成JSON格式的字符串,并写入到文件类对象fp中。
  • json.dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

    • 将Python对象编码成JSON格式的字符串,返回该字符串。
  • json.load(fp, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

    • 从文件类对象fp中读取JSON格式的字符串,并将其解码成Python对象。
  • json.loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

    • 将JSON格式的字符串s解码成Python对象。

综合示例——CSV和JSON相互转化

需求

可以让CSV和JSON相互转化

不传入目录就在当前目录查找和输出

带操作耗时

源文件CSV

BattleID,StartTime,EndTime,Duration,WinnerID,LoserID,EventID,Timestamp,EventType,ActorID,ActorName,TargetID,TargetName,SkillID,SkillName,Damage,Effect,Outcome
1,2024-05-01 10:00:00,2024-05-01 10:05:00,300,1,2,1,2024-05-01 10:00:05,"攻击",1,"英雄A",2,"英雄B",,"普通攻击",100,,"击中"
1,2024-05-01 10:00:10,2024-05-01 10:05:00,300,1,2,2,2024-05-01 10:00:15,"技能释放",2,"英雄B",1,"英雄A",1,"冰霜新星",150,"冰冻","成功"
1,2024-05-01 10:00:20,2024-05-01 10:05:00,300,1,2,3,2024-05-01 10:00:25,"攻击",1,"英雄A",2,"英雄B",,"普通攻击",120,,"闪避"
1,2024-05-01 10:00:30,2024-05-01 10:05:00,300,1,2,4,2024-05-01 10:00:35,"技能释放",1,"英雄A",2,"英雄B",2,"火球术",200,"燃烧","成功"
2,2024-05-01 10:10:00,2024-05-01 10:15:00,300,3,4,5,2024-05-01 10:10:05,"攻击",3,"英雄C",4,"英雄D",,"普通攻击",90,,"击中"
2,2024-05-01 10:10:10,2024-05-01 10:15:00,300,3,4,6,2024-05-01 10:10:15,"技能释放",4,"英雄D",3,"英雄C",3,"治疗波",0,"治疗","成功"
2,2024-05-01 10:10:20,2024-05-01 10:15:00,300,3,4,7,2024-05-01 10:10:25,"攻击",3,"英雄C",4,"英雄D",,"普通攻击",110,,"击中"
2,2024-05-01 10:10:30,2024-05-01 10:15:00,300,3,4,8,2024-05-01 10:10:35,"技能释放",3,"英雄C",4,"英雄D",4,"雷霆一击",170,"眩晕","成功"
3,2024-05-01 10:20:00,2024-05-01 10:25:00,300,5,6,9,2024-05-01 10:20:05,"攻击",5,"英雄E",6,"英雄F",,"普通攻击",80,,"击中"
3,2024-05-01 10:20:10,2024-05-01 10:25:00,300,5,6,10,2024-05-01 10:20:15,"技能释放",6,"英雄F",5,"英雄E",5,"暗影突袭",130,"恐惧","成功"
3,2024-05-01 10:20:20,2024-05-01 10:25:00,300,5,6,11,2024-05-01 10:20:25,"攻击",5,"英雄E",6,"英雄F",,"普通攻击",100,,"闪避"
3,2024-05-01 10:20:30,2024-05-01 10:25:00,300,5,6,12,2024-05-01 10:20:35,"技能释放",5,"英雄E",6,"英雄F",6,"光辉之箭",160,"眩晕","成功"

代码

import csv
import json
import os
import time

class DataConverter:
    @staticmethod
    def csv_to_json(csv_file_path, json_file_path=None):
        start_time = time.time()
        
        # 如果没有提供完整路径,尝试在当前目录查找文件
        if not os.path.isfile(csv_file_path):
            csv_file_path = os.path.join(os.getcwd(), csv_file_path)
        
        # 确定CSV文件所在的目录和文件名
        directory, csv_filename = os.path.split(csv_file_path)
        filename, _ = os.path.splitext(csv_filename)
        
        # 如果没有指定json_file_path,构建JSON文件路径
        if json_file_path is None:
            json_file_path = os.path.join(directory, filename + '.json')
        elif not os.path.isabs(json_file_path):  # 如果提供的是相对路径
            json_file_path = os.path.join(os.getcwd(), json_file_path)
        
        # 读取CSV文件并转换为JSON
        data = []
        with open(csv_file_path, mode='r', encoding='utf-8') as csv_file:
            csv_reader = csv.DictReader(csv_file)
            for row in csv_reader:
                data.append(row)
        
        # 写入JSON文件
        with open(json_file_path, 'w', encoding='utf-8') as json_file:
            json_file.write(json.dumps(data, indent=4, ensure_ascii=False))
        
        elapsed_time = time.time() - start_time
        print(f"JSON文件已创建于:{json_file_path}。操作耗时 {elapsed_time:.6f} 秒。")


    @staticmethod
    def json_to_csv(json_file_path, csv_file_path=None):
        start_time = time.time()
        
        # 如果没有提供完整路径,尝试在当前目录查找文件
        if not os.path.isfile(json_file_path):
            json_file_path = os.path.join(os.getcwd(), json_file_path)
        
        # 确定JSON文件所在的目录和文件名
        directory, json_filename = os.path.split(json_file_path)
        filename, _ = os.path.splitext(json_filename)
        
        # 如果没有指定csv_file_path,构建CSV文件路径
        if csv_file_path is None:
            csv_file_path = os.path.join(directory, filename + '.csv')
        elif not os.path.isabs(csv_file_path):  # 如果提供的是相对路径
            csv_file_path = os.path.join(os.getcwd(), csv_file_path)
        
        # 读取JSON文件并转换为CSV
        with open(json_file_path, 'r', encoding='utf-8') as json_file:
            data = json.load(json_file)
        
        # 写入CSV文件
        if data:
            with open(csv_file_path, 'w', encoding='utf-8', newline='') as csv_file:
                writer = csv.DictWriter(csv_file, fieldnames=data[0].keys())
                writer.writeheader()
                for row in data:
                    writer.writerow(row)
        
        elapsed_time = time.time() - start_time
        print(f"CSV文件已创建于:{csv_file_path}。操作耗时 {elapsed_time:.6f} 秒。")

# 使用示例
# 将CSV转换为JSON
DataConverter.csv_to_json('example.csv')

# 将JSON转换回CSV
DataConverter.json_to_csv('example.json')

这段代码定义了一个名为 DataConverter 的类,它包含两个静态方法:csv_to_jsonjson_to_csv。这两个方法分别用于将 CSV 文件转换为 JSON 格式,以及将 JSON 文件转换回 CSV 格式。下面是对整段代码的详细解释:

  • DataConverter:这是一个工具类,提供了 CSV 和 JSON 文件格式相互转换的功能。

  • 静态方法 csv_to_json(csv_file_path, json_file_path=None):这个方法接受一个 CSV 文件路径作为输入,并将其转换为 JSON 格式。转换后的 JSON 文件路径可以作为第二个参数提供,如果不提供,则默认在 CSV 文件所在的同一目录下创建一个同名的 JSON 文件。

  • 静态方法 json_to_csv(json_file_path, csv_file_path=None):这个方法接受一个 JSON 文件路径作为输入,并将其转换回 CSV 格式。转换后的 CSV 文件路径可以作为第二个参数提供,如果不提供,则默认在 JSON 文件所在的同一目录下创建一个同名的 CSV 文件。

方法详细解释

csv_to_json 方法
  1. 开始计时:记录方法开始执行的时间,以便计算整个操作的耗时。
  2. 处理文件路径
    • 首先检查提供的 CSV 文件路径是否指向一个实际存在的文件。如果不是,尝试在当前工作目录下查找该文件。
    • 提取 CSV 文件的目录和文件名,用于确定输出文件的位置和名称。
    • 如果未提供 JSON 文件路径,或提供的是相对路径,构建输出 JSON 文件的完整路径。
  3. 读取 CSV 并转换为 JSON
    • 使用 csv.DictReader 读取 CSV 文件,将每行转换为字典对象,并添加到列表中。
    • 将列表转换为 JSON 格式的字符串,并写入到指定的 JSON 文件中。
  4. 记录耗时并输出结果:计算操作耗时,并输出转换后的 JSON 文件路径和耗时信息。
json_to_csv 方法
  1. 开始计时:同上,记录方法开始执行的时间。
  2. 处理文件路径
    • 类似于 csv_to_json 方法,检查和处理 JSON 文件路径,确定输出 CSV 文件的位置和名称。
  3. 读取 JSON 并转换为 CSV
    • 读取 JSON 文件内容,将其解析为 Python 对象(通常是列表或字典)。
    • 使用 csv.DictWriter 将解析后的数据写入到 CSV 文件中。首先写入表头(即字典的键),然后写入每行数据(字典的值)。
  4. 记录耗时并输出结果:计算操作耗时,并输出转换后的 CSV 文件路径和耗时信息。

使用示例

代码的最后部分展示了如何使用 DataConverter 类将一个 CSV 文件转换为 JSON 格式,以及如何将一个 JSON 文件转换回 CSV 格式。这通过调用类的静态方法并传入相应的文件路径来实现。

附件

1. 战斗事件表(BattleEvents)

这个表用于记录战斗中发生的所有事件,每一行代表一个独立的事件。

字段名称数据类型描述
EventIDINT PRIMARY KEY AUTO_INCREMENT事件的唯一标识符
BattleIDINT关联的战斗ID,用于将事件与特定的战斗关联起来
TimestampDATETIME事件发生的时间戳
EventTypeVARCHAR(50)事件类型(如“攻击”、“技能释放”、“死亡”等)
ActorIDINT事件发起者的ID(例如攻击者或技能释放者)
TargetIDINT事件目标的ID(如被攻击者或技能作用对象),如果适用
SkillIDINT使用的技能ID,如果事件类型是技能释放
DamageINT造成的伤害量,如果适用
EffectVARCHAR(255)特殊效果的描述(如“眩晕”、“冰冻”等),如果适用
OutcomeVARCHAR(255)事件结果的简短描述,如“击杀”、“技能被闪避”等

2. 战斗表(Battles)

这个表用于记录每一场战斗的基本信息。

字段名称数据类型描述
BattleIDINT PRIMARY KEY AUTO_INCREMENT战斗的唯一标识符
StartTimeDATETIME战斗开始的时间戳
EndTimeDATETIME战斗结束的时间戳
WinnerIDINT获胜方的ID
LoserIDINT失败方的ID
DurationINT战斗持续时间(秒)

3. 角色表(Characters)

这个表用于记录战斗中出现的角色(包括英雄和单位)的信息。

字段名称数据类型描述
CharIDINT PRIMARY KEY AUTO_INCREMENT角色的唯一标识符
NameVARCHAR(50)角色的名称
TypeVARCHAR(50)角色的类型(如“英雄”、“单位”)
IconVARCHAR(255)角色图标的路径

4. 技能表(Skills)

这个表用于记录游戏中技能的信息。

字段名称数据类型描述
SkillIDINT PRIMARY KEY AUTO_INCREMENT技能的唯一标识符
NameVARCHAR(50)技能的名称
DescriptionVARCHAR(255)技能的描述
IconVARCHAR(255)技能图标的路径
转载自:https://juejin.cn/post/7365644073015066661
评论
请登录