【问题标题】:How to convert a csv file to a Dictionary in Python?如何在 Python 中将 csv 文件转换为字典?
【发布时间】:2021-12-18 20:56:40
【问题描述】:

我有一个 csv 文件,其中包含用于创建 yaml 文件的配置信息(最终所需的结果)。首先,我试图将 csv 文件的每一行转换为 Dictionary,然后我可以使用 yaml.dump(Created_Dictionary) 轻松地将 Dictionary 转换为 yaml 文件

示例输入文件(test.csv):

fieldname|type|allowed|coerce
field_A|String|10,20,30|to_str
field_B|Integer||to_int

我使用 pandas 库的源代码:

df = pd.read_csv("test.csv", "|")
df_to_dict = df.to_dict(orient='records')
print(df_to_dict) # print the dictionary

test_yaml = yaml.dump(df_to_dict)
print(test_yaml) # print the yaml file

我得到的字典输出(df_to_dict):

[{'fieldname': 'field_A', 'type': 'String', 'allowed': '10,20,30'}, {'fieldname': 'field_B', 'type': 'Integer', 'allowed': nan}]

我得到 yaml (test_yaml) 的输出:

- allowed: 10,20,30
  fieldname: field_A
  type: String
- allowed: .nan
  fieldname: field_B
  type: Integer

所需的字典输出 (df_to_dict) 是:

[
  {'field_A':
          {'type': 'String', 'allowed': '10,20,30', 'coerce': to_str}
       },
  {'field_B':
          {'type': 'String',  'allowed': '', 'coerce': to_int}
       } 
]

所需的 yaml 输出 (test_yaml) 是:

field_A:
  type: String
  allowed: 
  - '10'
  - '20'
  - '30'
  coerce: to_str
field_B:
  type: Integer
  allowed:
  coerce: to_int

我看到变量 df_to_dict 是一个字典列表。我是否必须遍历每个列表项,然后为每一行构建字典?我不理解正确的方法。任何帮助表示赞赏。

【问题讨论】:

  • 您所需的字典输出包含 CSV 中不可用的信息。您从哪里获得所有额外的字段/数据?
  • 如果你不需要或者不需要 Pandas,Python 的标准 csv 库和 DictReader 类可以处理这个问题;下面的解决方案。

标签: python pandas csv dictionary yaml


【解决方案1】:

试试:

df = pd.read_csv("test.csv", "|")
my_dict = df.set_index("fieldname").to_dict("index")

#convert allowed items to list
df["allowed"] = df["allowed"].str.split(",")
test_yaml = yaml.dump(df.set_index("fieldname").to_dict("index"), sort_keys=False)
输出:
>>> my_dict
{'field_A': {'type': 'String', 'allowed': '10,20,30', 'coerce': 'to_str'},
 'field_B': {'type': 'Integer', 'allowed': nan, 'coerce': 'to_int'}}

>>> print(test_yaml)
field_A:
  type: String
  allowed:
  - '10'
  - '20'
  - '30'
  coerce: to_str
field_B:
  type: Integer
  allowed: .nan
  coerce: to_int

【讨论】:

  • 感谢您的解决方案;它似乎有效,但如果字段名称如下所示,字典输出似乎很好,但 yaml 输出会根据字段名称按升序重新排序。尝试以下输入文件 `` fieldname|type|allowed field_A|String|10,20,30 Z_field|Integer| field_B|String|111 A_filed|Date|11042021 ```
  • @Aady - 我编辑了我的答案。包括sort_keys=False 以保留原始订单。
  • 再次感谢。但是我怎样才能将允许的值作为 yaml 列表。您可以在上面看到所需的输出。另外,我可以在这里使用 if 语句来调用 coerce 的函数吗? IE。如果是字符串,则强制 = to_str;如果是整数,则强制 = to_int
  • @Aady - 我再次编辑了它。请停止在 cmets 中提出后续问题和/或更改您的原始问题。如果需要,请发布一个新问题,如果相关,请链接此问题。
【解决方案2】:

如果您不需要 Pandas,并且我在您的描述或示例中没有看到任何需要,请使用 Python 的内置 csv 库及其 DictReader 类。

import csv
import pprint

yaml_d = {}
with open('sample.csv', newline='') as f:
    reader = csv.DictReader(f, delimiter='|')
    for row in reader:
        fname = row['fieldname']
        allowed = row['allowed'].split(',')

        yaml_d[fname] = row             # "index" row by fieldname
        yaml_d[fname]['allowed'] = allowed

        del yaml_d[fname]['fieldname']  # remove now-extraneous fieldname from row


pprint.pprint(yaml_d)

得到我:

{'field_A': {'allowed': ['10', '20', '30'],
             'coerce': 'to_str',
             'type': 'String'},
 'field_B': {'allowed': [''], 'coerce': 'to_int', 'type': 'Integer'}}

【讨论】:

  • 我也喜欢这个想法,因为它在迭代时给了我更多的控制权。你知道我怎样才能获得允许的 yaml 列表吗?上面的截图。
  • @Aady,我不确定yaml.dump() 是如何工作的,但我认为我上面的编辑可以解决问题。
【解决方案3】:

你想玩弄你的 pandas DataFrame 的索引。

>>> df = pd.read_csv("test.csv", sep="|", index_col=0)
>>> df
              type   allowed
fieldname                   
field_A     String  10,20,30
field_B    Integer       NaN
>>> df.to_dict(‘index’) # returns dict like {index -> {column -> value}}
{'field_A': {'type': 'String', 'allowed': '10,20,30'}, 'field_B': {'type': 'Integer', 'allowed': nan}}
>>> print(yaml.dump(df.to_dict(‘index’)))
field_A:
  allowed: 10,20,30
  type: String
field_B:
  allowed: .nan
  type: Integer

.nan 您必须处理自定义转储或过滤器。

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_dict.html?highlight=to_dict#pandas.DataFrame.to_dict

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html

【讨论】:

    猜你喜欢
    • 2018-08-13
    • 2021-12-22
    • 2017-09-13
    • 2020-12-24
    • 1970-01-01
    • 2021-04-01
    • 1970-01-01
    • 2023-03-20
    • 2017-03-27
    相关资源
    最近更新 更多