Python:将整数列表写入 .csv 文件并读回相同格式
Python: Writing list of integers to .csv file and reading back to same format
我有一个典型的复制和粘贴语法混淆,可能是因为我不太明白我在做什么!
我正在尝试保存从 mediapipe 库中收集的一系列 facemark_landmark 坐标。我遍历一部电影的帧,每一帧给我 468 个整数对,每个地标的屏幕坐标。
每一帧我都将坐标列表添加到名为 stored_data
的列表中
stored_data.append(landmark_coords)
电影结束后,我将数据写入文件:
with open("out.csv", "w") as f:
wr = csv.writer(f)
wr.writerows(stored_data)
这似乎工作正常,我的 csv 文件如下所示:(181, 95) , (170, 87) , .....
每行468对,电影每一帧一行。
但我在尝试将 csv 文件转换回正确格式时遇到了麻烦。
我目前的努力是:
stored_data = []
with open("out.csv", "r") as f:
rr = csv.reader(f)
for row in rr:
frland=[]
for l in row:
coords = [map(float,l.split(',')) for i in l]
frland.append(coords)
stored_data.append(frland)
我收到错误:ValueError:设置带有序列的数组元素。请求的数组在 1 维后具有不均匀的形状。检测到的形状是(468,)+不均匀部分。
谁能帮帮我?
根据我的经验,CSV 用于在不同的人和进程之间共享数据。 CSV 本身没有本机类型,所有内容都被序列化为字符串,但是,是的,现在您在尝试读回某些值时遇到了问题解码。
并且因为您必须解码,所以这是一个很好的指标,表明其他内容可能比 CSV 更好。如果您只需要在进程之间存储 mediapipe 结果,我重复 Ari 在评论中所说的,使用 pickle:它可以存储复杂类型,这样您就可以避免考虑编码和解码,并使其像“保存”一样简单,然后打开":
import pickle
orig_stored_data = [[(181, 95), (170, 87)], [(20, 40), (30, 50)]]
f_pickle = open("stored_data.pkl", "wb")
pickle.dump(orig_stored_data, f_pickle)
f_pickle = open("stored_data.pkl", "rb")
new_stored_data = pickle.load(f_pickle)
assert new_stored_data == orig_stored_data
如果您必须使用 CSV,则需要正确解释每一列中的元组。我认为这是不完整的:
coords = [map(float,l.split(',')) for i in l]
因为您在按逗号拆分之前没有删除括号。
更straight-forward的做法是使用ast模块中的literal_eval()函数:
import ast, csv, io, pprint
f_in = io.StringIO('"(181, 95)","(170, 87)"\n"( 20, 40)","(30,50)"')
stored_data = []
reader = csv.reader(f_in)
for row in reader:
frland = []
for col in row:
coords = ast.literal_eval(col)
frland.append(coords)
stored_data.append(frland)
和 stored_data
看起来像:
[[(181, 95), (170, 87)],
[(20, 40), (30, 50)]]
我有一个典型的复制和粘贴语法混淆,可能是因为我不太明白我在做什么!
我正在尝试保存从 mediapipe 库中收集的一系列 facemark_landmark 坐标。我遍历一部电影的帧,每一帧给我 468 个整数对,每个地标的屏幕坐标。
每一帧我都将坐标列表添加到名为 stored_data
的列表中stored_data.append(landmark_coords)
电影结束后,我将数据写入文件:
with open("out.csv", "w") as f:
wr = csv.writer(f)
wr.writerows(stored_data)
这似乎工作正常,我的 csv 文件如下所示:(181, 95) , (170, 87) , ..... 每行468对,电影每一帧一行。
但我在尝试将 csv 文件转换回正确格式时遇到了麻烦。
我目前的努力是:
stored_data = []
with open("out.csv", "r") as f:
rr = csv.reader(f)
for row in rr:
frland=[]
for l in row:
coords = [map(float,l.split(',')) for i in l]
frland.append(coords)
stored_data.append(frland)
我收到错误:ValueError:设置带有序列的数组元素。请求的数组在 1 维后具有不均匀的形状。检测到的形状是(468,)+不均匀部分。
谁能帮帮我?
根据我的经验,CSV 用于在不同的人和进程之间共享数据。 CSV 本身没有本机类型,所有内容都被序列化为字符串,但是,是的,现在您在尝试读回某些值时遇到了问题解码。
并且因为您必须解码,所以这是一个很好的指标,表明其他内容可能比 CSV 更好。如果您只需要在进程之间存储 mediapipe 结果,我重复 Ari 在评论中所说的,使用 pickle:它可以存储复杂类型,这样您就可以避免考虑编码和解码,并使其像“保存”一样简单,然后打开":
import pickle
orig_stored_data = [[(181, 95), (170, 87)], [(20, 40), (30, 50)]]
f_pickle = open("stored_data.pkl", "wb")
pickle.dump(orig_stored_data, f_pickle)
f_pickle = open("stored_data.pkl", "rb")
new_stored_data = pickle.load(f_pickle)
assert new_stored_data == orig_stored_data
如果您必须使用 CSV,则需要正确解释每一列中的元组。我认为这是不完整的:
coords = [map(float,l.split(',')) for i in l]
因为您在按逗号拆分之前没有删除括号。
更straight-forward的做法是使用ast模块中的literal_eval()函数:
import ast, csv, io, pprint
f_in = io.StringIO('"(181, 95)","(170, 87)"\n"( 20, 40)","(30,50)"')
stored_data = []
reader = csv.reader(f_in)
for row in reader:
frland = []
for col in row:
coords = ast.literal_eval(col)
frland.append(coords)
stored_data.append(frland)
和 stored_data
看起来像:
[[(181, 95), (170, 87)],
[(20, 40), (30, 50)]]