在Python中从2个CSV创建新输出(数据操作)

2024-10-03 17:24:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个名为cities的csv文件,格式如下:

City_id,City,Population,Weather,State
la01,LA,24,72,CA
ny01,NY,12,42,NY
bo01,BO,32,65,BO

另一个csv称为shipping:

Carrier,Type,Path,Packages,Max_Packages
UPS,Truck,la01-ny01,100,200
UPS,Truck,la01-bo01,100,200
UPS,Air,la01-ny01,100,500
UPS,Air,bo01-ny01,100,500

我需要将它们写入一个字符串,其中每行以城市开头,并有一个所有目的地的列表(列表应按类型排序):

la01:LA [Truck="ny01:100,200 + bo01:100,200" Air="ny01:100,500"];
bo01:BO [Air="ny01:100,500"];

我试图通过首先将cities csv读入字典,然后抓取每个键(city_id)并将其存储在列表中以供以后使用来打破这种局面。我会使用城市id来匹配配送csv,并通过循环查找所有路径,从我当前迭代的城市id开始。从那以后,我用if语句来检查承运人,并将这些值拆分成卡车或航空字典。然而,这个解决方案变得非常复杂,无法处理同一个精确路径字符串可能多次出现的事实。有更简单的方法吗


Tags: csvidcity列表packagesairlabo
1条回答
网友
1楼 · 发布于 2024-10-03 17:24:08

只需读取CSV并将数据转换为适合所需报告输出的格式。为此,字典可以方便地按城市对路线进行分组——使用城市作为字典键

import csv
from collections import defaultdict
from functools import partial
from operator import itemgetter

city_data = (r for r in csv.DictReader(open('city_data.csv', 'r')))
path_data = (r for r in csv.DictReader(open('path_data.csv', 'r')))

# Seems we only need city_data for id<=>city mapping. Simple dict works.
city_codes = {d['City_id']: d['City'] for d in city_data}

dest_data = defaultdict(partial(defaultdict, list))

package_data = itemgetter('Path', 'Type', 'Packages', 'Max_Packages')

for rec in path_data:
    path, type, packages, max = package_data(rec)
    city_id = path[:4]
    city    = city_codes[city_id]
    dest_data[f'{city_id}:{city}'][type].append(f"{path[5:]}:{packages},{max}")

dest_data然后包含:

defaultdict(..., 
    {
        'la01:LA': defaultdict(<class 'list'>, 
            {
                'Truck': ['ny01:100,200', 'bo01:100,200'], 
                'Air':   ['ny01:100,500']
            }), 
        'bo01:BO': defaultdict(<class 'list'>, 
            {
                'Air':   ['ny01:100,500']
            })
      })

现在,您已经按照您想要的方式组织了数据,只需像您在示例中那样调整数据以供显示

>>> for city, pkg_routes in dest_data.items():
...     pkg_info = (f'{type}="' + ' + '.join(pkg_list) + '"' 
...                 for type, pkg_list in pkg_routes.items())
...     print(f'{city} [' + ' '.join(pkg_info) + '];')
...     
la01:LA [Truck="ny01:100,200 + bo01:100,200" Air="ny01:100,500"];
bo01:BO [Air="ny01:100,500"];

路径数据可以迭代,字典可以通过两个键进行更新,这两个键可以转换为一个组和子组:按城市和按路线类型

使用一个defaultdict给我们一个空列表,以便在添加新密钥时添加路由信息,这非常方便

构造多级defaultdict的惯用方法是将partial对象作为参数传递给其构造函数。可以设置partial来创建一个子defaultdict,该子defaultdict根据需要生成新列表。在本例中,2级dict将为我们提供一个空列表,以便在添加新密钥时将路由信息附加到其中

itemgetter是另一个方便的工具,它可以一次从path_data字典中获取多个键并返回一个值元组

关于良好做法的最后一点说明。在指定理解时,最好使用生成器(括号与方括号),因为这样可以减少算法中的循环数。因此,path_dataCSV文件访问与生成最终字典的循环相结合

相关问题 更多 >