Python CSV 列表中的多个数字
我写了一个Python脚本,用来把PostgreSQL的输出存储到一个CSV文件中,这个CSV文件的一部分看起来是这样的:
我写了一些代码,逐行提取并将每第二个数字相乘,比如(看上面的照片),对于第二行,0.844 * 0.0 = 0;对于第四行,0.844 * 0.0 * 0.0 * 0.0 = 0。
import sys, os
os.chdir('C:\Users\Heinz\Desktop')
print os.getcwd()
#set up psycopg2 environment
import psycopg2
#driving_distance module
query = """
select *
from shortest_path ($$
select
gid as id,
source::int4 as source,
target::int4 as target,
pi::double precision as cost,
pi_rcost::double precision as reverse_cost
from network
$$, %s, %s, %s, %s
)
"""
#make connection between python and postgresql
conn = psycopg2.connect("dbname = 'TC_area' 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
import shutil
rs = []
ars = []
i = 1
l = 1
filename = 'test01.csv'
with open(filename, 'wb') as f:
while i <= k:
while l <= k:
cur.execute(query, (i, l, False, True))
rs.append(cur.fetchall())
element = list(rs)
[a[-1] for a in element]
product = reduce(lambda x,y: x * y, [a[-1] for a in element])
writer = csv.writer(f, delimiter = ',')
writer.writerow(product)
rs = []
l = l + 1
l = 1
i = i + 1
conn.close()
上面的代码可能会生成一个CSV文件,
因为每行的每个元素最后一个位置总是0,所以我在第三列得到了全是0的结果。
我该如何修改我原始脚本中的这两行代码?
[a[-1] for a in element]
product = reduce(lambda x,y: x * y, [a[-1] for a in element])
第一行提取每个子元组中的每第三个元素,但我不想提取每行最后一个子元组中的最后一个元素。
我的目标是乘以每个括号中的每第三个元素,但如果一行中有多个括号,就不包括最后一个;如果一行中只有一个括号,就将这个行的值设为1。
更新#1
我把代码修改成这样,
#run loops
#import csv module
import csv
import tempfile
import shutil
rs = []
ars = []
i = 1
l = 1
filename = 'test01.csv'
with open(filename, 'wb') as f:
while i <= k:
while l <= k:
cur.execute(query, (i, l, False, True))
rs.append(cur.fetchall())
element = list(rs)
[a[-1] for a in element]
product = 1 if len(element) == 1 else reduce(lambda x,y: x*y, [a[-1] for a in element[:-1]])
writer = csv.writer(f, delimiter = ',')
writer.writerow([product])
rs = []
l = l + 1
l = 1
i = i + 1
我在 writer.writerow([product])
这一行中把“product”放在了括号里,以防止出现序列预期错误,结果我得到了每列都包含1的CSV文件,
更新#2
我在脚本中稍微改了一下,测试了element的长度,
#run loops
#import csv module
import csv
import tempfile
rs = []
i = 1
l = 1
filename = 'test02.csv'
with open(filename, 'wb') as f:
cur.execute(query, (2, 3, False, True))
rs.append(cur.fetchall())
element = list(rs)
print len(element)
[a[-1] for a in element]
product = reduce(lambda x,y: x*y, [a[-1] for a in element[:-1]], 1)
writer = csv.writer(f, delimiter = ',')
writer.writerow(element)
rs = []
conn.close()
这是输出结果,
len(element) = 1
尽管一行中有2个元素,但Python返回的却是len(element) = 1(在EXCEL中点击B1单元格也可以证明,这个单元格是空的)
我猜在最后的更新中,A列全是1是因为所有元素的长度都等于1,所以下面的代码行无法生成有效的答案。
product = reduce(lambda x,y: x*y, [a[-1] for a in element[:-1]], 1)
我该如何修改脚本以获取元素的真实长度?
更新#3
我想直接得到一个乘积矩阵,因此我写了这个脚本,
import sys, os
os.chdir('C:\Users\Heinz\Desktop')
#print os.getcwd()
#set up psycopg2 environment
import psycopg2
#pgRouting module
query = """
select *
from shortest_path ($$
select
gid as id,
source::int4 as source,
target::int4 as target,
pi::double precision as cost,
pi_rcost::double precision as reverse_cost
from network
$$, %s, %s, %s, %s
)
"""
#make connection between python and postgresql
conn = psycopg2.connect("dbname = 'TC_area' 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
#import csv module
import csv
import tempfile
import shutil
#run loops
rs = []
i = 1
l = 1
filename = 'rs.csv'
with open(filename, 'wb') as f:
writer = csv.writer(f, delimiter = ',')
while i <= k:
while l <= k:
cur.execute(query, (i, l, False, True))
rs.append(cur.fetchall())
l = l + 1
l = 1
writer.writerow(rs)
rs = []
i = i + 1
conn.close()
这是CSV文件中的样子,
这次每行中的每个字段都包含查询行的输出,
query, (i, l, False, True)
字段内容不同,例如,
- 字段A1包含[(1, -1, 0.0)]
- 字段B1包含[(1, 1, 0.844), (2, -1, 0.0)]
所以现在我需要计算每行每个字段中有多少个元素,并使用mtadd提供的答案脚本来计算乘积。
我能否获取一个字段中元素的数量?
2 个回答
在执行以下代码后:
rs.append(cur.fetchall())
element = list(rs)
这个元素变成了一个长度为1的列表,里面唯一的内容就是查询结果中的所有行。你需要把它改成:
element = cur.fetchall()
要计算乘积,可以使用:
product = reduce(lambda x,y: x*y, [a[-1] for a in element[:-1]],1)
将reduce的初始化值设置为1。
因为 writerow 需要一个列表作为参数,所以在你的例子中,element 的内容实际上是 [[(2, 2, 0.0), (3, -1, 0.0)]]
,也就是一个包含子元组的列表的列表。这个子元组的内部列表是通过 fetchall 返回的。
我们逐行看看你的代码,以及它在更新2中为你的示例电子表格生成的内容。
cur.execute(query, (2, 3, False, True))
temp = cur.fetchall()
print temp
这会返回一个元组的列表 [(2,2,0.0), (3,-1,0.0)]
,这正是你期望的结果。问题出现在:
rs.append(temp)
当你调用 rs.append 时,你把从数据库返回的元组列表放进了另一个列表中,这样就创建了一个包含元组列表的列表,比如 [[(2,2,0.0), (3,-1,0.0)]]
。外层列表的长度是1,也就是说,它里面包含了1个元组列表。
element = list(rs)
这会创建一个新的列表,它是 rs 的浅拷贝,但结构上和 rs 是一样的,仍然是一个包含元组列表的列表。
所以,把你的代码改成下面这样的形式应该能解决你的问题:
filename = 'test02.csv'
with open(filename, 'wb') as f:
cur.execute(query, (2, 3, False, True))
element = cur.fetchall()
print len(element)
if len(element) == 1:
product = [1]
else:
product = reduce(lambda x,y: x*y, [a[-1] for a in element[:-1]], 1)
writer = csv.writer(f, delimiter = ',')
writer.writerow(element)