【问题标题】:Add data to specific column using writerows, lambda使用 writerows,lambda 将数据添加到特定列
【发布时间】:2022-01-23 20:38:27
【问题描述】:

我已经遍历通过 API 查询返回给我的 JSON 对象,并且可以将数据 (obj_key1) 获取到我的 target_csv,但数据显示在第一列,而不是 data 列,我正在尝试指定。

示例 JSON:

[{'obj_key': 0.5,
  'obj_key1': 4000,
  'obj_key2': '2020-05-01',
  'obj_key3': 0.0,
  'obj_key4': 'US',
  'obj_key5': 50000,
  'obj_key6': 11,
  'obj_key7': 0.0,
  'obj_key8': 20000,
  'obj_key9': 0.01,
  'obj_key10': '6786547',
  'obj_key11': None,
  'obj_key12': 12},
 {'obj_key': 0.4,
  'obj_key1': 5000,
  'obj_key2': '2020-05-02',
  'obj_key3': 0.0,
  'obj_key4': 'US',
  'obj_key5': 657435,
  'obj_key6': 112,
  'obj_key7': 0.0,
  'obj_key8': 678548,
  'obj_key9': 0.032,
  'obj_key10': '6786547',
  'obj_key11': None,
  'obj_key12': 13},...]

代码:

import csv
import json
import requests

token = {token}

with open('../folder/file.csv') as src, open('target_file.csv', 'w', newline='') as tgt:
    reader = csv.reader(src)
    writer = csv.writer(tgt)

    columns = next(reader)

    writer.writerow(columns)

    headers = {
        'Authorization': token,
        'Content-Type': 'application/json; charset=utf-8',
    }

    for id, name, date, data in reader:

        response = requests.get(f'https://{base_url}/api/endpoint?start_date=2021-05-01&end_date=2021-05-15' + '&id=' + str(id),
            headers=headers
        )

        response_data = response.json()
        for i in range(len(response_data)):
            data = writer.writerows(map(lambda x: [response_data[i]['obj_key1']], range(1)))

预期的 CSV 输出:

id name date data
6786547 Name 2020-05-01 4000
6786547 Name 2020-05-02 5000

【问题讨论】:

  • 您只获得最后一个日期的数据,因为每次执行 data = response_data[i]['obj_key'] 行时,它都会替换之前的 data 值——所以在 for 循环结束时分配的最后一个东西它将是它的价值。
  • @martineau 谢谢,我注意到这就是正在发生的事情。我面临的问题是解决这个问题,因此所有值都添加到 CSV,而不仅仅是替换前一个值的最后一个值。
  • 我真的不知道输入数据的格式或 CSV 每一行中的内容,基本上你必须在 data 循环内做一些事情 - 也许写一行CSV 或累积值并使用其中一个以上的内容写入行。
  • 我用我最近的编辑更新了上面的代码,得到了每个对象的单独数据,但现在它只显示在第一行,所以现在我必须弄清楚如何将其写入特定的“数据”列。
  • 如果您编辑了您的问题并展示了 JSON 数据的样子以及转换为 CSV 格式后的样子的示例,将会很有帮助。

标签: python json api csv


【解决方案1】:

我将推荐一些看起来非常不同,但应该可以完成工作的东西。

对我来说,最重要的想法是将流程分成不同的部分——这样每个人都更容易理解。

先阅读

我已选择将所有 API 读取保存到字典列表中,将在下一部分中使用 CSV DictWriter 写出。

import csv
import requests

path = f'https://{base_url}/api/endpoint?start_date=2021-05-01&end_date=2021-05-15'
token = {token}
headers = {
    'Authorization': token,
    'Content-Type': 'application/json; charset=utf-8',
}

final_rows = []
with open('../folder/file.csv') as src:
    reader = csv.reader(src)
    next(reader)  # discard this header, will be created from dict row

    for my_id, name, date in reader:  # omitted `data` from input
        response = requests.get(path + f'&id={my_id}', headers=headers)

        # Assuming `response.json()` looks like the sample JSON you provided
        for json_data in response.json():
            final_row = {
                'id': my_id,
                'name': name,
                'date': date,
                'data': json_data['obj_key1']
            }

        final_rows.append(final_row)

我模拟了final_rows,看起来像:

final_rows = [
    {
        'id': '6786547',
        'name': 'Name',
        'date': '2020-05-01',
        'data': '4000'
    },
    {
        'id': '6786547',
        'name': 'Name',
        'date': '2020-05-02',
        'data': '5000'
    }
]

然后,写

现在,final_rows 几乎会自己写:

with open('target_file.csv', 'w', newline='') as tgt:
    writer = csv.DictWriter(tgt, fieldnames=final_rows[0].keys())
    writer.writeheader()
    writer.writerows(final_rows)

我得到:

id,name,date,data
6786547,Name,2020-05-01,4000
6786547,Name,2020-05-02,5000

【讨论】:

  • 或者只是writer.writerows(final_rows)
  • @chepner,谢谢,修改了我的代码!
【解决方案2】:

下面是如何实现我在comment 中建议的关于多次调用writerow() 并将其传递给所有四列(idnamedatedata)的方法。您也许可以对其进行优化以先创建行,然后再调用writerows(),但我怀疑这是否值得。

请注意,您忽略了响应中列表的每个对象的 'obj_key2' 中的 date 并使用正在读取的 CSV 文件中的对象,这对我来说似乎很奇怪——但这似乎是您在你的问题。

import csv
import json
import requests

token = {token}

with open('../folder/file.csv', 'r', newline='') as src, \
     open('target_file.csv', 'w', newline='') as tgt:
    reader = csv.reader(src)
    writer = csv.writer(tgt)

    writer.writerow(next(reader) + ['data'])  # Copy header row and add column.

    headers = {'Authorization': token,                           
               'Content-Type': 'application/json; charset=utf-8'}

    for id, name, date, data in reader:
        response = requests.get(
            f'https://{base_url}/api/endpoint?start_date=2021-05-01&end_date=2021-05-15' 
            f'&id={id}', headers=headers)

        for obj in response.json():
            writer.writerow([id, name, date, obj['obj_key1']])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多