在Python中从2个CSV中创建新的输出 (数据处理)

问题描述 投票:0回答:1

我有一个叫城市的csv文件,格式是这样的。

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

和另一个叫航运的csv文件。

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"];

我试图通过先把城市的cv文件读到一个字典里,然后抓取每个键(city_id)并把它存储在一个列表中,以便以后使用。我会使用城市id来匹配运输csv,并有一个循环,寻找所有的路径,从我当前迭代的任何城市id开始。从那里,我有if语句来检查Carrier,并打算将值拆分到Truck或Air字典中。然而,这个解决方案变得非常复杂,而且不能处理同一路径字符串可能出现多次的事实。有什么更简单的方法吗?

python csv dictionary output data-manipulation
1个回答
0
投票

这只是一个读取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 按需生成新的列表。在这个例子中,当一个新的键被添加到列表中时,2-level dict会给我们一个空列表来追加路径信息。

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

最后一个关于良好实践的小说明。当指定一个理解(括号与方括号)时,使用一个生成器是很好的,因为这样可以减少算法中的循环次数。因此,在 path_data CSV文件的访问与循环相结合,产生最终的字典。

© www.soinside.com 2019 - 2024. All rights reserved.