Python字典含有元组列表转换为CSV文件

4

如何处理类似这样的 Python 字典:

{
    'RCLS1': [(0, 20),  (10, 112),  (20, 130), (30, 102)],
    'RCLS2': [(0, 16),(10, 53),(20, 96), (30, 45)]
}

将其转换为带有以下结构的CSV文件:

RCLS1,  0,  20
RCLS1, 10, 112
.
.
.
RLCS2, 30,  45

我尝试过这个:

with open(r'E:\data.csv', "wb") as f:
    csv.writer(f).writerows((k,) + v for k, v in dct.items())

但是这导致了以下错误:
can only concatenate tuple (not "list") to tuple

2
你希望输出的结果是什么样子的?目前,v 是一个元组列表,所以 (k,) + v 试图将一个 元组 添加到一个元组列表中,而这是行不通的。 - AChampion
2
@AChampion 同意。你能提供一个预期输出的例子吗? - Preston Martin
感谢您的评论。同意,我对预期输出的解释写得不好。现在已经包含了一个例子。 - JacamoFinane
3个回答

2
如果我理解你的问题正确,你正在尝试做类似于这样的事情(不需要使用csv模块):
a = {'RCLS1':[(0, 20),  (10, 112),  (20, 130), (30, 102)], 'RCLS2': [(0, 16),(10, 53),(20, 96), (30, 45)]}

with open('E:\data.csv', 'a+') as f:
    for k,v in a.items():
        f.write("{0}: {1}\n".format(k,", ".join(", ".join(str(j) for j in k) for k in v)))

输出(您文件中的日期将类似于此输出):

RCLS1: 0, 20, 10, 112, 20, 130, 30, 102
RCLS2: 0, 16, 10, 53, 20, 96, 30, 45

否则,如果你想按对获取数据,可以像这样做:
with open('E:\data.csv', 'a+') as f:
    for k,v in a.items():
        f.write("{0}: {1}\n".format(k, "".join(", ".join(str(k) for k in v))))

输出:

RCLS1: (0, 20), (10, 112), (20, 130), (30, 102)
RCLS2: (0, 16), (10, 53), (20, 96), (30, 45)

编辑:

针对您的新更新,有一个快速解决方案。您可以像这样做:

a = {'RCLS1':[(0, 20),  (10, 112),  (20, 130), (30, 102)], 'RCLS2': [(0, 16),(10, 53),(20, 96), (30, 45)]}

with open('E:\data.csv', 'a+') as f:
    for k,v in a.items():
        for j in v:
            f.write("{0}: {1}\n".format(k, ", ".join(str(k) for k in j)))

输出:

RCLS2: 0, 16
RCLS2: 10, 53
RCLS2: 20, 96
RCLS2: 30, 45
RCLS1: 0, 20
RCLS1: 10, 112
RCLS1: 20, 130
RCLS1: 30, 102

1
非常感谢您的想法。看了我的原始描述,我理解了您的建议。您介意看一下我提供的输出格式示例(在编辑问题后)吗?谢谢。 - JacamoFinane
1
谢谢你,@ChihebNexus,你上次建议的方法符合我想要的输出。感谢你提供的所有建议。学到了新东西! - JacamoFinane

1
根据您提供的样本输入/输出,您可以遍历字典的键值对,然后遍历与每个键关联的元组值列表,构建关联的CSV行字符串,并将其写入CSV文件,如下所示:
dct = {'RCLS1':[(0, 20),  (10, 112),  (20, 130), (30, 102)], 'RCLS2': [(0, 16),(10, 53),(20, 96), (30, 45)]}
int_to_str = lambda int_value: str(int_value)

with open(r"data.csv", "w") as csv_file:
    for key, values in dct.items():
         for tuple_value in values:
             csv_row = [key] + list(map(int_to_str, list(tuple_value)))
             csv_file.write(", ".join(csv_row) + "\n")

"

data.csv 的结果:

"
RCLS2, 0, 16
RCLS2, 10, 53
RCLS2, 20, 96
RCLS2, 30, 45
RCLS1, 0, 20
RCLS1, 10, 112
RCLS1, 20, 130
RCLS1, 30, 102

谢谢您的想法。我已经编辑了问题以澄清输出。之前我的表述不够清晰,对此我深感抱歉。如果您可以再看一眼并分享您的想法,我将不胜感激。非常感谢。 - JacamoFinane
1
@JacamoFinane 不用谢。你可以尝试一下更新后的答案吗? - Robert Valencia
这看起来很棒,@Robert Valencia,谢谢你向我展示了一种有效的方法来达到所需的输出。感谢你的指导。我学到了新东西。 - JacamoFinane
欢迎,@JacamoFinane!如果这个答案对您有帮助/解决了您的问题,请点赞/接受答案。 - Robert Valencia
亲爱的@Robert Valencia,我正在尝试各种解决方案,并且尝试您的建议会导致“TypeError:can only concatenate list (not "map") to list”出现在“csv_row = [key] + map(int_to_str, list(tuple_value))”这一行。您有什么建议可以解决这个问题吗? - JacamoFinane
1
@JacamoFinane 这个错误在Python 3中发生,因为map返回一个可迭代对象,所以返回值应该显式地转换为列表。请查看更新的答案并告诉我是否有效。 - Robert Valencia

1
一种使用 pandas 的替代答案是:

>>> import pandas as pd
>>> d={'RCLS1':[(0, 20),  (10, 112),  (20, 130), (30, 102)], 'RCLS2': [(0, 16),(10, 53),(20, 96), (30, 45)]}
>>> df=pd.DataFrame(d)


       RCLS1     RCLS2
0    (0, 20)   (0, 16)
1  (10, 112)  (10, 53)
2  (20, 130)  (20, 96)
3  (30, 102)  (30, 45)
[4 rows x 2 columns]

>>> dfs=df.stack().reset_index(level=0)

       level_0          0
RCLS1        0    (0, 20)
RCLS2        0    (0, 16)
RCLS1        1  (10, 112)
RCLS2        1   (10, 53)
RCLS1        2  (20, 130)
RCLS2        2   (20, 96)
RCLS1        3  (30, 102)
RCLS2        3   (30, 45)


>>> dfs=dfs[0].apply(pd.Series)  # break the tuples in column with "name"=0

        0    1
RCLS1   0   20
RCLS2   0   16
RCLS1  10  112
RCLS2  10   53
RCLS1  20  130
RCLS2  20   96
RCLS1  30  102
RCLS2  30   45


>>> dfs.to_csv('fileName.csv')

谢谢@ab-user216125,这也很完美,因为我希望能够熟练掌握多种方法来解决同一个问题。这将被添加到我的工具库中!谢谢。 - JacamoFinane
我正在尝试各种解决方案,@ab-user216125。我的字典中有成千上万的条目,不幸的是其中一些值的长度与其他值不同,因此在调用df=pd.DataFrame(d)时会出现错误"arrays must all be same length"。我想知道在这种情况下,pandas DF是否仍然是一个选项? - JacamoFinane
如果您的RCLS1和RCLS2或RCLSn长度发生变化,您可能会得到稀疏的数据框。在这种情况下,您需要考虑您的数据是否符合您的预期。Pandas可以很好地处理缺失数据,可以通过删除行/列或填充缺失值来处理。您将如何处理这些事情完全取决于您自己。如果您喜欢这个答案,请投票支持 - 每个人都喜欢赚积分 ;) - B.Kocis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接