在CSV文件中逐行循环数字

1 投票
3 回答
3322 浏览
提问于 2025-04-18 09:41

我写了一个Python脚本,用来在PostgreSQL中运行SQL语句,

import sys, os, math
os.chdir(r'C:\Users\Heinz\Desktop')
print os.getcwd()

#set up psycopg2 environment
import psycopg2

#shortest_path module
query = """
    select *
    from shortest_path ($$
        select
            gid as id,
            source::int4 as source,
            target::int4 as target,
            cost::double precision as cost,
            rcost::double precision as reverse_cost
        from network
        $$, %s, %s, %s, %s
    )
"""

#make connection between python and postgresql
conn = psycopg2.connect("dbname = 'test' user = 'postgres' host = 'localhost' password = 'xxxx'")
cur = conn.cursor()

#count rows in the table
cur.execute("select count(*) from network")
result = cur.fetchone()
k = result[0] + 1                #number of points = number of segments + 1

#run loops
#import csv module
import csv
import tempfile

element = []
i = 1
l = 1
filename = 'pi_value.csv'
with open(filename, 'wb') as f:
    while i <= k:
        while l <= k:
            cur.execute(query, (i, l, True, True))
            element = cur.fetchall()
            product = sum([a[-1] for a in element[:-1]])
            writer = csv.writer(f, delimiter = ',')
            writer.writerow([product])
            element = []
            l = l + 1
        l = 1
        i = i + 1

你可以看到我使用了从i到k(还有从l到k)的迭代器来做while循环,现在我有一个包含我想要的迭代器i和l的数字的csv文件。例如,这就是我的csv文件,

在这里输入图片描述

我希望迭代器能从第一行开始,逐行循环,就像在最里面的while循环中那样,l = 6, l = 31, l = 28,..., l = 17,i也从6开始,但只有在l变到17时,i才会移动到i = 31,然后再回到l = 6,依此类推。

我该怎么写额外的代码来读取这个csv文件,让while循环中的迭代器按照文件里的数字来运行呢?


更新#1

我试了这个,

element = []

with open('tc_sta_id.csv') as f1, open('pi_value.csv', 'wb') as f2:
csvs = csv.reader(f1)
col_num = 0
rows = list(csvs)
k = len(rows)
for row in csvs:
    i = row[col_num]
    l = row[col_num]
    while i <= k:
        while l <= k:
            cur.execute(query, (i, l, True, True))
            element = cur.fetchall()
            product = sum([a[-1] for a in element[:-1]])
            writer = csv.writer(f2, delimiter = ',')
            writer.writerow([product])
            element = []
            l = l + 1
        l = row[col_num]
        i = i + 1

脚本运行得很好,但输出的csv文件里全是空白,请给我一些建议来解决这个问题!

3 个回答

0

我给你做了一个简单的测试,使用了基本的Python功能。

f = open('test.csv')
csvlines = f.readlines()
f.close()
numbers = [int(n.split(',')[0]) for n in csvlines]

你可能需要根据你操作系统的地区设置,把','替换成';'或者其他符号。

简单解释一下: csvlines会包含你的csv文件中的每一行,格式是字符串,比如说 ['1,a,some text', '2,b,some other text']。你会逐行处理这些内容,并对每一行使用split方法,比如说 '1,a,some text'.split(',') 会得到 ['1','a','some text']。你的第一列需要转换成整数,因为它现在还是字符串形式。

在你的代码中使用如下(根据问题的修改进行了编辑):

for i in numbers:
    if(i<k):
        for l in numbers:
            # not sure what your constraint on k is, but you can stop iterating 
            # through the numbers with a simple if
            if(l<k):
                #do work (you can use i an l here, they will automatically 
                # take the next value each iteration of the for loop 
                #(try print i, l for example): 6,6; 6,31; ...; 6,17; 31,6; 31,31
1

col_num是你存放i值的那一列的列号。

with open('yourfile') as file:
    csv = csv.reader(file)
    next(csv) # skip the header
    col_num = 0
    for row in csv:
        i = row[col_num]
        while i <= k:
            cur.execute(query, (i, 100000000000, True, True))
            rs.append(cur.fetchall())
            i = i + 1
1

由于你的问题从一开始就发生了很大变化,我决定单独给你一个回答。这是专门针对你更新的第一个问题的回答。

你的while循环的条件是错误的。你的条件是基于csv文件中的行数(在你的例子中是8)。你把这个行数和csv中找到的数字(比如6、31等)进行比较。这就意味着每次当你遇到第二个数字(31大于8)时,while循环就会停止。此外,你并没有跳到csv中的下一个元素,而只是简单地加1。我没有尝试运行你的代码,但我觉得你是在循环:i=6,7,8,而l也分别是6,7,8。然后它尝试31,立刻停止,因为其他的数字也是大于8的。

我不太确定你想要什么,因为你似乎一直想用额外的while循环来做某些事情,但我不明白你想用它们来做什么(在你的问题中找不到相关信息,所有内容都只暗示使用for循环)。

我也不确定i和l是否来自同一个csv文件。我给你做了一个解决方案,你可以很容易地让i和l来自不同的csv文件,但我一开始设定它们来自同一个。如果它们来自同一个csv,你不能简单地用相同的迭代器嵌套for循环,所以我们采用了一个小技巧,把它们提取到一个列表中(我用一个简单的例子测试过这个)。

rows = list(csvs) #convert to a list to avoid problems with iterating over the same iterator
csv_for_i = rows
csv_for_l = rows
for row_i in csv_for_i:
    i = row_i[col_num]
    for row_l in csv_for_l:
        l = row_l[col_num]
        cur.execute(query, (i, l, True, True))
        element = cur.fetchall()
        product = sum([a[-1] for a in element[:-1]])
        writer = csv.writer(f2, delimiter = ',')
        writer.writerow([product])
        element = []

如果这个方法有效,请告诉我。如果有效,请接受这个回答,我会考虑如何把问题和回答整理得更好,以便在Stack Overflow上更好地使用。目前,这里实际上有多个问题和回答,这对其他寻找答案的人来说很困惑。


顺便说一下,给你一个关于迭代器常见陷阱的小例子(虽然是用csv做的,但适用于所有迭代器)。

import csv

# test.csv contents:
#
#6
#31
#17

print 'Case 1:'
with open('test.csv') as f1:
    csv1 = csv.reader(f1)
    csv2 = csv.reader(f1)
    for el1 in csv1:
        for el2 in csv2:
            print el1, el2
# Results
#
#['6'] ['31']
#['6'] ['17']

print 'Case 2:'
with open('test.csv') as f1:
    csvs = csv.reader(f1)
    rows = list(csvs)
    for el1 in rows:
        for el2 in rows:
            print el1, el2
# Results
#
#['6'] ['6']
#['6'] ['31']
#['6'] ['17']
#['31'] ['6']
#['31'] ['31']
#['31'] ['17']
#['17'] ['6']
#['17'] ['31']
#['17'] ['17']

print 'Case 3:'
with open('test.csv') as f1, open('test.csv') as f2:
    for el1 in csv.reader(f1):
        for el2 in csv.reader(f2):
            print el1, el2
# Results
#
#['6'] ['6']
#['6'] ['31']
#['6'] ['17']

print 'Case 4:'
with open('test.csv') as f1, open('test.csv') as f2:
    csv1 = csv.reader(f1)
    csv2 = csv.reader(f2)
    for el1 in csv1:
        for el2 in csv2:
            print el1, el2
# Results
#
#['6'] ['6']
#['6'] ['31']
#['6'] ['17']

撰写回答