Python,从csvs处理数组并插入数据库

时间:2019-05-16 15:51:13

标签: python arrays postgresql csv

我想读取多个csv文件作为数组,并根据每一行中第一个条目的数值来复制这些数组的行(如果该值为1,则不会重复,但是如果该值是3,则该行代表3次)。处理完数组后,我想将它们插入到db表中。

示例csv文件:

mult, n1, n2, n3, n4
1, 23.2, 55, 0, 1.1
3, 6.6, 0.2, 5, 9
1, 2.2, 5, 8, 9
2, 3.3, 10, 2, 2

mult, n1, n2, n3, n4
2, 23.2, 55, 0, 1.1
3, 6.6, 0.2, 5, 9
1, 2.2, 5, 8, 9
1, 3.3, 10, 2, 2

期望的结果

[[1, 23.2, 55, 0, 1.1],
[3, 6.6, 0.2, 5, 9],
[3, 6.6, 0.2, 5, 9],
[3, 6.6, 0.2, 5, 9],
[1, 2.2, 5, 8, 9],
[2, 3.3, 10, 2, 2],
[2, 3.3, 10, 2, 2]]

[[2, 23.2 55, 0, 1.1],
[2, 23.2 55, 0, 1,1],
[3, 6.6, 0.2, 5, 9],
[3, 6.6, 0.2, 5, 9],
[3, 6.6, 0.2, 5, 9],
[1, 2.2, 5, 8, 9],
[1, 3.3, 10, 2, 2]]

最初,我以列表形式读取csvs,然后有一个for循环,根据row [0]中的数字将每一行插入db中。

当前有效的基本代码段:

import csv, os, glob
import psycopg2

path = "/home/user/Desktop/files/*.csv"

for fname in glob.glob(path):
    self.readFile(fname)

with open(filename, 'r') as f:
    arr= list(csv.reader(f)) 
    iter_arr = iter(arr)
    next(iter_arr)

    for row in iter_arr:                   
        mult = int(float(row[0]))
        for i in range (mult):
            try:
                self.cur.execute("INSERT INTO csv_table VALUES (%s, %s, %s, %s, %s)", row)

             except Exception, exc:     
                 locked = True
                 print ("%s", exc)     

以上代码的工作方式是,它将在数据库表中加载正确数量的行,但是我认为在将行加载到数据库之前复制行会更有用,这样我就可以操作数组中的数据如果需要,还可以更改或添加值。

我早些时候问过一个有关使用numpy的问题,它使我能够正确地操纵一些随机生成的数组,但是与其将行复制为单独的元素,还不如将它们彼此复制。我不知道如何调整它的大小以使其正常工作,而且看起来还不错。调整大小似乎不起作用,我得到了('%s', TypeError('not all arguments converted during string formatting',))

a = ([list(map(float, row)) for row in csv.reader(f)])
aa = np.asarray(a)
result = ([np.tile(aa[i], aa[i, 1].astype(int)) for i in range(aa.shape[0])])result = np.asarray(result)

结果

[[1, 23.2, 55, 0, 1.1],
[3, 6.6, 0.2, 5, 9,
3, 6.6, 0.2, 5, 9,
3, 6.6, 0.2, 5, 9],
[1, 2.2, 5, 8, 9],
[2, 3.3, 10, 2, 2,
2, 3.3, 10, 2, 2]]

[[2, 23.2 55, 0, 1.1,
2, 23.2 55, 0, 1,1],
[3, 6.6, 0.2, 5, 9,
3, 6.6, 0.2, 5, 9,
3, 6.6, 0.2, 5, 9],
[1, 2.2, 5, 8, 9],
[1, 3.3, 10, 2, 2]]

2 个答案:

答案 0 :(得分:1)

这对您有用吗?我从上面将您的字符串转换为列表,然后遍历每一行并将其附加到最终数组中

a = """mult, n1, n2, n3, n4
1, 23.2, 55, 0, 1.1
3, 6.6, 0.2, 5, 9
1, 2.2, 5, 8, 9
2, 3.3, 10, 2, 2
2, 23.2, 55, 0, 1.1
3, 6.6, 0.2, 5, 9
1, 2.2, 5, 8, 9
1, 3.3, 10, 2, 2"""

a = a.split('\n')

final = a[0]
for line in a[1:]:
    for i in range(int(line[0])):
        final.append(line)

答案 1 :(得分:0)

您可以创建一个generator函数,该函数接受可迭代的行(例如csv.reader),检查每一行以确定应重复多少次,并为每一行提供所需的数字的时间。

import csv


def generate_rows(rows):
    for row in rows:
        num_repeats = int(row[0])
        for _ in range(num_repeats):
            yield row


if __name__ == '__main__':
    with open('test.csv', newline='') as f:
        reader = csv.reader(f)
        next(reader)    # skip headers
        for row in generate_rows(reader):
            print(row)

给出您的第一个示例csv,程序将产生以下输出:

['1', '23.2', '55', '0', '1.1']
['3', '6.6', '0.2', '5', '9']
['3', '6.6', '0.2', '5', '9']
['3', '6.6', '0.2', '5', '9']
['1', '2.2', '5', '8', '9']
['2', '3.3', '10', '2', '2']
['2', '3.3', '10', '2', '2']

如果要在列表中收集输出,只需在生成器函数上调用list:

rows = list(generate_rows(iterable))