繁体   English   中英

如何将值列表写入csv文件中的“单元格”?

[英]How to write a list of values to a "cell" in a csv file?

我有一个循环,它为每次迭代生成一个值列表。 我希望将该值列表保存为 csv“单元格”中的单个字符串。 具体来说,我所拥有的是以下内容:

数据

#a csv file that looks something like this:
index,username,user_id
1,name1,1
2,name2,2
...
users = pd.read_csv(csv_file, usecols= ['username', 'user_id'])

for row in users.itertuples(index=True, name='Pandas'):
     get_data(username, user_id)

get_data返回字符串列表。 我不想以逗号分隔的方式将这些字符串写入 csv 文件,而是希望以嵌套的方式将它们写入 csv。 类似于以下内容:

index,username,user_id,data
1,name1,1,[string1,string2,string3,string4,...]
2,name2,2,[string5,string6,string7,string8,...]
...

更新:

我想以这种形式存储我的结果的原因之一是我计划为每个用户保存更多数据。 此数据的长度可能与我的get_data调用的输出长度不同。

问题的两个关键概念:

  1. Pandas .to_csv()在自动引用方面非常聪明。 即使数据包含文字引号或逗号,在不更改默认分隔符的情况下读取/写入 csv 文件应该没有问题。

  2. 读取这种格式的问题:最初是列表的数据单元格在 csv 文件中以字符串形式存储,因此它们以字符串形式加载。 ast.literal_eval()可以将列表的字符串表示形式转换回列表。 注意:此措施可能容易受到脏数据的影响。 请务必在保存 csv 文件之前执行数据清理。

实验代码

import pandas as pd
import ast  # for literal string parsing

# data
df = pd.DataFrame(
    data={
        "index": range(1,5),
        "username": [f"name{i}" for i in range(4)],
        "user_id": range(1,5),
        # initialize each data cell with an empty list
        "data": [list() for _ in range(4)]
    }
)

# use `.at[]` to append some values
df.at[0, "data"] += [1, 2, 3]
df.at[2, "data"] += [4]
# mixed types, quotes and commas
df.at[3, "data"] += [1, '"', -3.3, "'", ",,,", ";"]

print(df)

# save
file_path = "/mnt/ramdisk/out.csv"
df.to_csv(file_path)

# load
df_read = pd.read_csv(file_path, index_col=0)
# parse, because contents in data cells were loaded as strings
for i in range(len(df_read)):
    s = df_read.iat[i, 3]
    print(f"row {i} before: {type(s)}")
    df_read.iat[i, 3] = ast.literal_eval(s)
    print(f"       after: {type(s)}, len={len(s)}")

print(df_read)  # identical to df

# check elements within list
ls = df_read.iat[3,3]
for i in range(len(ls)):
    print(f"row {i}: {type(ls[i])}, contents={ls[i]}")

结果

(0) 原始数据框(没有打印引用,但不影响数据本身)

df
Out[7]: 
index username  user_id                     data
0      1    name0        1                [1, 2, 3]
1      2    name1        2                       []
2      3    name2        3                      [4]
3      4    name3        4  [1, ", -3.3, ', ,,,, ;]

(1) 原始 csv 文件

bill@bill-laptop-deb: /mnt/ramdisk
$ cat out.csv                                                                                                                                                    
,index,username,user_id,data
0,1,name0,1,"[1, 2, 3]"
1,2,name1,2,[]
2,3,name2,3,[4]
3,4,name3,4,"[1, '""', -3.3, ""'"", ',,,', ';']"

(2)在python中重新加载文件

df_read  # identical to input
Out[8]: 
index username  user_id                     data
0      1    name0        1                [1, 2, 3]
1      2    name1        2                       []
2      3    name2        3                      [4]
3      4    name3        4  [1, ", -3.3, ', ,,,, ;]

(3) LibreOffice 6 也能正确导入 csv 文件。

(4) 对加载的数据进行类型检查

ls = df_read.iat[3,3]  # a mixed-up list
for i in range(len(ls)):
    print(f"row {i}: {type(ls[i])}, contents={ls[i]}")

row 0: <class 'int'>, contents=1
row 1: <class 'str'>, contents="
row 2: <class 'float'>, contents=-3.3
row 3: <class 'str'>, contents='
row 4: <class 'str'>, contents=,,,
row 5: <class 'str'>, contents=;

可以看到,尽管引用/转义使人眼难以阅读文件,但对 Pandas 和 LibreOffice 来说应该不是问题。

旁注:为了可追溯性和数据完整性,强烈建议使用数据库。 这种连续的数据增强场景正是数据库系统的设计目标。 如果你的项目独立运行,SQLite 应该是一个轻量级的选择,在部署方面相对容易。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM