如何一次讀取兩行輸入 CSV,將一些值組合成新的單行,然后將該行寫入新的 CSV?
在下面的輸入中,我想讀取兩行,從第二行獲取 price1 并將其設定為新的組合行中的 price2,然后對接下來的兩行重復:
輸入
date, name, qt, price1
9/12/22, AB, 2, 5.00
9/12/22, AB, 2, 5.08
9/12/22, BC, 1, 2.00
9/12/22, BC, 1, 2.03
新的 csv
date, name, qt, price1, price2
9/12/22, AB, 2, 5.00, 5.08
9/12/22, BC, 1, 2.00, 2.03
import csv
data = []
with open('test.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
data.append({'date': row[0], 'qt': row[3], 'name': row[5], 'price': row[10]})
#data.append(myClass(row[0], row[2], row[3], row[5], row[10]))
for x in data:
print(x)
缺少阿德里安的答案:
- 匯入 csv
- #newline 需要 python 3
- csv 必須是 UTF-8 并且標頭必須匹配
uj5u.com熱心網友回復:
cat price_old.csv
date,name,qt,price1
9/12/22,AB,2,5.00
9/12/22,AB,2,5.08
9/12/22,BC,1,2.00
9/12/22,BC,1,2.03
with open("price_old.csv") as old_csv:
new_list = []
dt, nm = None, None
c_reader = csv.DictReader(old_csv)
for row in c_reader:
if row['date'] != dt and row['name'] != nm:
dt, nm = row['date'], row['name']
price_list = [row['price1']]
else:
price_list.append(row['price1'])
row.update({'price1': price_list[0], 'price2': price_list[1]})
new_list.append(row)
price_list = []
dt, nm = None, None
with open('price_new.csv', 'w', newline='') as new_csv:
c_writer = csv.DictWriter(new_csv, fieldnames= ['date', 'name','qt', 'price1', 'price2'])
c_writer.writeheader()
c_writer.writerows(new_list)
cat price_new.csv
date,name,qt,price1,price2
9/12/22,AB,2,5.00,5.08
9/12/22,BC,1,2.00,2.03
uj5u.com熱心網友回復:
使用pandas將使您的生活更輕松。
import pandas as pd
df = pd.read_csv('test.csv', delimiter=', ')
# Group by the first 3 columns, and use the rows to form the columns (unstack)
df = df.groupby(['date','name','qt'])['price1'].apply(
lambda df: df.reset_index(drop=True)).unstack().reset_index()
# Rename the columns
df.columns = [*df.columns[:-2], 'price1', 'price2']
df.to_csv('output.csv', sep=',', index=False)
是output.csv:
date,name,qt,price1,price2
9/12/22,AB,2,5.0,5.08
9/12/22,BC,1,2.0,2.03
uj5u.com熱心網友回復:
Python 的 csv 閱讀器可以輕松地一次讀取任意數量的行。
讀取器(csv.reader 和 csv.DictReader)都是迭代器,這意味著我們可以使用 next() 函式手動獲取一行,就像我們可以使用elem = next(my_iterator)任何迭代器中的下一個元素一樣:
import csv
import pprint
new_rows = []
with open("input.csv", newline="") as f:
reader = csv.reader(f)
header = next(reader)
new_rows.append(header [" price 2"])
row1 = next(reader)
row2 = next(reader)
new_rows.append(row1 row2[:-1])
row1 = next(reader)
row2 = next(reader)
new_rows.append(row1 row2[:-1])
pprint.pprint(new_rows)
給我們:
[
['date', ' name', ' qt', ' price1', ' price 2'],
['9/12/22', ' AB', ' 2', ' 5.00', ' 5.08'],
['9/12/22', ' BC', ' 1', ' 2.00', ' 2.03']
]
這種方法可以適應使用 for 回圈來驅動迭代。for 回圈將始終為我們提供我們想要的當前行組中的“第一行”。在回圈內部,我們要求與組中一樣多的下一行:
with open("input.csv", newline="") as f:
reader = csv.reader(f)
header = next(reader)
new_rows.append(header [" price 2"])
for row1 in reader:
row2 = next(reader)
new_rows.append(row1 row2[-1:])
這種方法假設您的輸入有一個標題,然后行數是組大小的偶數倍。如果你的輸入不符合這個,你會得到一個 StopIteration 例外,它看起來像(在 3.11 中):
File "/Users/zyoung/develop/StackOverflow/./main.py", line 31, in <module>
row2 = next(reader)
^^^^^^^^^^^^
StopIteration
如果有可能,您可以添加例外處理:
for row1 in reader:
try:
row2 = next(reader)
except StopIteration as e:
print(f"encountered an odd row on line {reader.line_num}; stopping reading, moving on to writing")
break
最后,我們可以將此想法擴展到邏輯組中的任意數量的行,例如每組 3 行:
date, name, qt, price1
9/12/22, AB, 2, 5.00
9/12/22, AB, 2, 5.08
9/12/22, AB, 2, 5.12
9/12/22, BC, 1, 2.00
9/12/22, BC, 1, 2.03
9/12/22, BC, 1, 2.06
header = next(reader)
new_rows.append(header [" price 2", " price 3"])
for row1 in reader:
row2 = next(reader)
row3 = next(reader)
new_rows.append(row1 row2[-1:] row3[-1:])
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/529511.html
標籤:PythonCSV
