使用 writerows,lambda 将数据添加到特定列
Posted
技术标签:
【中文标题】使用 writerows,lambda 将数据添加到特定列【英文标题】:Add data to specific column using 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 格式后的样子的示例,将会很有帮助。
【参考方案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()
并将其传递给所有四列(id
、name
、date
和data
)的方法。您也许可以对其进行优化以先创建行,然后再调用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']])
【讨论】:
以上是关于使用 writerows,lambda 将数据添加到特定列的主要内容,如果未能解决你的问题,请参考以下文章
csv.writerow 在添加 for 循环后现在可以工作了吗?
Python,repl.it - 未使用 csv.writer 和 writer.writerow 将详细信息写入文件
如何将JSON数据添加到HTML AWS lambda响应主体?
Node.js中的代码AWS Lambda Package不会调用putRecord()来将数据添加到AWS Kinesis Firehose Stream中