具有两个变量唯一组合的Python数据格式

时间:2018-08-08 14:14:22

标签: python json csv dictionary

我仍然是Python的初学者(除了现在正在做的数据收集之外,我很少使用它)。 我有几个CSV,这些CSV基本上是有关几年中由ID标识的几台机器的信息的集合。 是这样的:

ID,Year,Variable1,Variable2
1,1990,x,y
1,1991,a,b
1,1992,f,g
2,2000,a,b
2,2001,a,b

现在,我的目标是尝试将数据收集为易于处理的格式。实际上,当前数据分散在多个CSV中,我想将其设为单个JSON文件。

编辑1:其他CSV包含每年数据或以下格式的常规数据:

ID,VariableX,VariableY
1,X,Y
2,X,Y

因此,我想我的第一个问题将是关于我应该使用哪种数据结构来读取和存储CSV数据。我考虑过使用字典,但是我不认为字典可以有两个键。然后我以为我可以将某种列表作为键,但是我不知道如何以JSON格式正确存储信息。

这就是我今天寻求您帮助的原因。

谢谢。

祝你有美好的一天

最后,我希望我的JSON对象具有单个ID,其中包含多年的所有数据,例如:

编辑2:

{
   "ID": "1"
   "1990": {
      "Variable1":"x"
      "Variable2":"y"
   }
   "1991": {...}
) 

1 个答案:

答案 0 :(得分:2)

有几种可用的选项。从概念上讲,可能是最简单的字典,它是一个键入到元组(id, year)的字典,其值是元组(variable1,variable2)或dict,例如

>>> {(1, 1990): {'v1': 'x', 'v2': 'y'}}
{(1, 1990): {'v1': 'x', 'v2': 'y'}}

不过,我会考虑创建一个对象来表示此数据,因为随着您的前进,问题和您的要求可能会变得更加复杂,并且一个对象使您可以定义方法以应对新的要求。

一个中间解决方案是一个namedtuple,下面是一个简单的例子:

>>> from collections import namedtuple
>>> Machine = namedtuple("Machine", ['id', 'year', 'variable1', 'variable2'])
>>> Machine(1, 1990, 'x', 'y')
Machine(id=1, year=1990, variable1='x', variable2='y')
>>> machines = [Machine(1, 1990, 'x', 'y'), Machine(1, 1991, 'a', 'b'), Machine(2, 2000, 'a', 'b')]
>>> machines_dict = {(m.id, m.year): m for m in machines}
>>> machines_dict[(2, 2000)]
Machine(id=2, year=2000, variable1='a', variable2='b')
>>> 

(有关更多信息,请参见documentation

请注意,namedtuples在json序列化程序中不能很好地发挥作用,因此我仍然倾向于一个简单的对象,该对象知道如何发出其数据字典,适合进行序列化。

我所说的“知道如何发出其数据字典的对象”通常仅表示该对象具有一种可以产生适当键和形状的字典的方法,例如

def to_dict(self):
  return {"ID": self.id, "year": self.year, "vars": (self.v1, self.v2)}

但是,您需要一些幻想的东西,想要汇总实例之间的数据。这将需要获取对象(或数据blob)列表,并进行一些解析以按ID分组并按年份列出实例。像这样:

@staticmethod
def machines_to_dict(machines):
  machines_by_id = defaultdict(list)
  for m in machines:
    machines_by_id[m.id].append(m)
  # now you have machines grouped by id
  return {id: years_to_vars_dict(machines) 
     for id, machines in machines_by_id.items()}

def years_to_vars_dict(machines):
  return {machine.year: {"Var1": machine.var1, 
                         "Var2": machine.var2}
          for machine in machines}

应该工作。 (但请记住,这未经测试,仅供参考,而不是工作代码)