Python:将csv数据与dict()相乘

Python:将csv数据与dict()相乘,python,csv,Python,Csv,我在下面发布了一个工作正常的代码。它目前所做的是: 它打开2个.csv文件“CMF.csv”和“D65.csv”,然后 对它进行一些数学运算 以下是这些文件的简单结构: “CMF.csv”(波长,x,y,z) “D65.csv”:(波长,a,b) 我有第三个文件data.csv,具有以下结构(序列号、波长、测量值、名称): 我想做的是能够编写几行代码来执行 最后一个文件的所有序列的数学(序列由序列号和名称定义) 例如,我需要一个循环,它将针对每个名称或序列号以及每个波长执行以下操作: x*a*测

我在下面发布了一个工作正常的代码。它目前所做的是:

它打开2个
.csv
文件“CMF.csv”和“D65.csv”,然后 对它进行一些数学运算

以下是这些文件的简单结构:

“CMF.csv”(波长,x,y,z)

“D65.csv”:(波长,a,b)

我有第三个文件
data.csv
,具有以下结构(序列号、波长、测量值、名称):

我想做的是能够编写几行代码来执行 最后一个文件的所有序列的数学(序列由序列号和名称定义)

例如,我需要一个循环,它将针对每个名称或序列号以及每个波长执行以下操作:

x*a*测量

我试图将data.csv`与其他文件一样加载到csv阅读器中,但无法加载

有什么想法吗

谢谢

import csv

with open('CMF.csv') as cmf:
    reader = csv.reader(cmf)
    dict_cmf = dict()
    for row in reader:
        dict_cmf[float(row[0])] = row

with open('D65.csv') as d65:
    reader = csv.reader(d65)
    dict_d65 = dict()
    for row in reader:
        dict_d65[float(row[0])] = row

with open('data.csv') as sp:
    reader = csv.reader(sp)
    dict_sp = dict()
    for row in reader:
        dict_sp[float(row[0])] = row

Y = 0
Y_total = 0
X = 0
X_total = 0
Z = 0 
Z_total = 0
i = 0
j = 0


for i in range(400, 700, i+10):

    X = float(dict_cmf[i][1]) * float(dict_d65[i][1])
    X_total = X_total + X
    Y = float(dict_cmf[i][2]) * float(dict_d65[i][1])
    Y_total = Y_total + Y
    Z = float(dict_cmf[i][3]) * float(dict_d65[i][1]) 
    Z_total = Z_total + Z   


wp_X = 100 * X_total / Y_total
wp_Y = 100 * Y_total / Y_total
wp_Z = 100 * Z_total / Y_total

print Y_total
print "D65_CMF_2006_10_deg white point = "
print wp_X, wp_Y, wp_Z
我明白了:

Traceback (most recent call last): File "C:\Users\gary\Documents\eclipse\Spectro\1illum_XYZ2006_D65_numpy.py", line 24, in <module> dict_sp[row[0]] = row IndexError: list index out of range
Traceback(最后一次调用):文件“C:\Users\gary\Documents\eclipse\Spectro\1illum\u XYZ2006\u D65\u numpy.py”,第24行,在dict\u sp[row[0]=行索引器中:列表索引超出范围

data.csv
中的一行或多行不包含您认为的内容。尝试将您的语句放入Try…except块中,以查看问题所在:

with open('spectral_data.csv') as sp:
    reader = csv.reader(sp)
    dict_sp = dict()
    for row in reader:
        try:
            dict_sp[float(row[0])] = row
        except IndexError as e:
            print 'The problematic row is:'
            print row
            raise e
在这种情况下,适当的调试器也会有所帮助


这可能是更好的方法,但是如果您想要一个香草Python的示例,您可以看看这个示例:

import csv
from collections import defaultdict

d = defaultdict(dict)
for fname, cols in [('CMF.csv', ('x', 'y', 'z')), ('D65.csv', ('a', 'b'))]:
    with open(fname) as ifile:
        reader = csv.reader(ifile)
        for row in reader:
            wl, values = int(row[0]), row[1:]
            d[wl].update(zip(cols, map(float, values)))

measurements = defaultdict(dict)
with open('data.csv') as ifile:
    reader = csv.reader(ifile)
    cols = ('measurement', 'name')
    for serial, wl, me, name in reader:
        measurements[int(serial)][int(wl)] = dict(zip(cols, (float(me), str(name))))

for serial in sorted(measurements.keys()):
    for wl in sorted(measurements[serial].keys()):
        me = measurements[serial][wl]['measurement']
        print me * d[wl]['x'] * d[wl]['a']
这会将x、y、z、a和b存储在字典中,并将波长作为键(没有明显的理由将这些值存储在单独的dict中)

测量值存储在两级深字典中,其中包含键
串行
波长
。通过这种方式,您可以迭代所有序列和所有对应的波长,如代码后面部分所示


对于示例中数据的具体计算,使用此结构可以非常轻松地完成:

tot_x = sum(v['x']*v['a'] for v in data.values())
tot_y = sum(v['y']*v['a'] for v in data.values())
tot_z = sum(v['z']*v['a'] for v in data.values())

wp_x = 100 * tot_x / tot_y
wp_y = 100 * tot_y / tot_y # Sure this is correct? It will always be 100
wp_z = 100 * tot_z / tot_y

print wp_x, wp_y, wp_z # 798.56037811 100.0 3775.04316468

以下是问题中输入文件提供的词典:

>>> from pprint import pprint
>>> pprint(dict(data))
{400: {'a': 82.7549,
       'b': 14.708,
       'x': 0.01879338,
       'y': 0.002589775,
       'z': 0.08508254},
 410: {'a': 91.486,
       'b': 17.6753,
       'x': 0.08277331,
       'y': 0.01041303,
       'z': 0.3832822},
 420: {'a': 93.4318,
       'b': 20.995,
       'x': 0.2077647,
       'y': 0.02576133,
       'z': 0.9933444}}
>>> pprint(dict(measurements))
{0: {400: {'measurement': 2.21, 'name': '1'},
     410: {'measurement': 2.22, 'name': '1'},
     420: {'measurement': 2.22, 'name': '1'}},
 1: {400: {'measurement': 2.21, 'name': '2'},
     410: {'measurement': 2.22, 'name': '2'},
     420: {'measurement': 2.22, 'name': '2'}}}

你需要熊猫。您可以将这些文件读入pandas表中,然后将它们连接起来,用以下代码替换您的代码:

import pandas

cmf = pandas.read_csv('CMF.csv', names=['wavelength', 'x', 'y', 'z'])
d65 = pandas.read_csv('D65.csv', names=['wavelength', 'a', 'b'])
data = pandas.read_csv('data.csv', names=['serialNumber', 'wavelength', 'measurement', 'name'])

lookup = pandas.merge(cmf, d65, on='wavelength')
merged = pandas.merge(data, lookup, on='wavelength')

totals = ((lookup[['x', 'y', 'z']].T*lookup['a']).T).sum()
wps  = totals/totals['y']

print totals['y']
print "D65_CMF_2006_10_deg white point = "
print wps
现在,这并没有做最后一点,您要为每个测量计算额外的值。您可以通过向
合并的
中添加列来完成此操作,如下所示:

merged['newcol'] = merged.x * merged.a * merged.measurement

当您尝试加载“Spectrum_data.csv”时,您的错误是什么?在您的问题中,您试图打开'spectral_data.csv',但调用文件'data.csv'。您好,很抱歉名称不匹配。我刚刚编辑了代码并使用与其他文件相同的技术添加了loading data.csv,我将“a”、“b”名称更改为一些数字并保留float()我得到的错误是
Traceback(最近一次调用):文件“C:\Users\gary\Documents\eclipse\Spectro\1illum\u XYZ2006\u D65\u numpy.py”,第24行,dict\u sp[行[0]]=行索引器:列出索引超出范围
请将回溯添加到Q:)这听起来很有趣,但是你的代码的结果不是我想要的:白点的伪代码是针对每个波长做y*a=s,然后将s添加到总值中。然后对所有波长做。x*a=u和z*a=v,然后将u与total_x相加,将v与total_z相加,然后白点是x=total_x/Y,Y=total_Y/Y,z=total_z/ZI。我们已将总计计算更改为包含每个关联a的乘法。很抱歉。上面的代码使用关联的a值对前两个文件中的每个波长执行此操作。计算的其余部分如您所述。您在何处添加此项
merged['newcol']=merged.x*merged.a*merged.measurement
您只需在末尾添加。我想你会想要一个更具描述性的名称来描述这个产品所代表的任何东西。好吧,我有一个新问题:如何计算从文件
data.csv
中提取的数据集的新结果,并带有序列号约束?即,仅计算序列号0、1、2等定义的序列:
>>> from pprint import pprint
>>> pprint(dict(data))
{400: {'a': 82.7549,
       'b': 14.708,
       'x': 0.01879338,
       'y': 0.002589775,
       'z': 0.08508254},
 410: {'a': 91.486,
       'b': 17.6753,
       'x': 0.08277331,
       'y': 0.01041303,
       'z': 0.3832822},
 420: {'a': 93.4318,
       'b': 20.995,
       'x': 0.2077647,
       'y': 0.02576133,
       'z': 0.9933444}}
>>> pprint(dict(measurements))
{0: {400: {'measurement': 2.21, 'name': '1'},
     410: {'measurement': 2.22, 'name': '1'},
     420: {'measurement': 2.22, 'name': '1'}},
 1: {400: {'measurement': 2.21, 'name': '2'},
     410: {'measurement': 2.22, 'name': '2'},
     420: {'measurement': 2.22, 'name': '2'}}}
import pandas

cmf = pandas.read_csv('CMF.csv', names=['wavelength', 'x', 'y', 'z'])
d65 = pandas.read_csv('D65.csv', names=['wavelength', 'a', 'b'])
data = pandas.read_csv('data.csv', names=['serialNumber', 'wavelength', 'measurement', 'name'])

lookup = pandas.merge(cmf, d65, on='wavelength')
merged = pandas.merge(data, lookup, on='wavelength')

totals = ((lookup[['x', 'y', 'z']].T*lookup['a']).T).sum()
wps  = totals/totals['y']

print totals['y']
print "D65_CMF_2006_10_deg white point = "
print wps
merged['newcol'] = merged.x * merged.a * merged.measurement