2014-02-18 38 views
1

我有一组数据,它有三个维度X,Y,Z顺序为24,67,95, 和8个变量:a,b,c,d ,e,f,g,h最快的方法来组合和归一化来自多维多维数组的数据

每个变量存储在[X,Y,Z] numpy数组()中,即24 * 67 * 95 = 152760的值。

将数组组合成一个OrderedDict(),其中的键是变量的名称。

所以,变量a为尺寸x的值,Y,Z是由数据给出[ '一'] [X] [Y] [Z]

欲这个数据插入到一个MySQL表中的归一化格式,它是由X,Y索引,Z:

--------------------- 
|x|y|z|a|b|c|d|e|f|g|h| 
--------------------- 
| | | | | | | | | | | | 

我以下面的方式,其中在x的每个步骤产生67 * 95 = 6365条目的插入语句这样做,我知道这是MySQL的最佳数量级:

cur = db.cursor() 
Xs = 24 
Ys = 67 
Zs = 95  
variables = ['a','b','c','d','e','f','g','h'] 
for x in range(Xs): 
    sql="insert into mytable (X,Y,Z" 
    for variable in variables: 
     sql+=","+variable 
    sql+=") values" 
    for y in range(Ys): 
     for z in range(Zs): 
      sql+="(%d,%d,%d" % (x,y,z) 
      for variable in variables: 
       sql+=","+str(data[variable][x][y][z]) 
      sql+=")," 
    cur.execute(sql[:-1]) 

整个循环在我的四核PC上每次迭代运行需要大约24秒的时间,只需要执行插入语句的约0.5秒。

有没有更快的方法来组合和规范化这些变量在内存中? (我知道标准化的数据库可能不是这种多维数据的最佳存储格式,这是我随后将测试的 - 对于这个问题的目的,假设它是)

谢谢!

+1

尝试使用生成的浮动代码生成一个长字符串与SQL命令 - 它只需要不到2.5秒在我的笔记本电脑上。如果我理解你的帖子,你有24 * 67 * 95 * 8的数字。别的东西似乎在吃掉你的时间。 – Dietrich

+0

两个小建议:(1)Numpy数组被索引为'array [x,y,z]',但是你使用了'array [x] [y] [z]'。 (2)将SQL命令的各个部分收集到一个列表中,并在最后执行一个'str.join',以避免每次分配一个越来越长的字符串(你不能真正追加到Python中的字符串,因为它们是不可变的)。 – 2014-02-18 23:53:28

+0

也许更好,在数组上调用'tolist()'方法并为嵌套列表建立索引,因为它比索引一个numpy数组更快。 – 2014-02-19 00:04:06

回答

1

只要看一段代码,我认为有很多事情可以改进。以下是我的看法:

cur = db.cursor() 
Xs = 24 
Ys = 67 
Zs = 95  
variables = ['a','b','c','d','e','f','g','h'] 
sql = ("INSERT INTO mytable (X, Y, Z, " + 
     ', '.join(variables) + 
     ') VALUES ({0})').format(','.join(['%s'] * (len(variables) + 3))) 

for x in range(Xs): 
    for y in range(Ys): 
     values = [] 
     for z in range(Zs): 
      values = [x, y, z] 
      for variable in variables: 
       values.append(data[variable][x][y][z]) 
      cur.execute(sql, values) 

SQL语句只创建一次。这些值存储在列表中,该列表在光标的​​方法时传递。

如何进一步改进它是将所有值存储在列表中并使用executemany()

all_values = [] 
for x in range(Xs): 
    for y in range(Ys): 
     values = [] 
     for z in range(Zs): 
      values = [x, y, z] 
      for variable in variables: 
       values.append(data[variable][x][y][z]) 
      all_values.append(values) 

cur.executemany(sql, all_values) 

我无法测试上述,因为我没有测试数据,但我希望它清楚哪些变化。

+0

正如我在上面的评论,似乎按元素访问原始数据结构元素的调用是缓慢的部分,并且通过将所有数据提取到新字典中,该过程已经加速了超过100次。但是,我也实施了您的解决方案,并且将速度再次提高了一倍,因此我会将此标记为所述问题的正确答案。谢谢! – meepmeep