這是我上一個問題的延續。我有 2 個檔案,file1.csv 和一個名為 master_file.csv 的大型 csv。它們有幾個列,并有一個名為 EMP_Code 的通用列名。
檔案 1 示例:
| EMP_name | EMP_代碼 | EMP_部門 |
|---|---|---|
| b | f367 | 美國廣播公司 |
| 一個 | c264 | xyz |
| C | d264 | 美國廣播公司 |
master_file 示例:
EMP_name EMP_age EMP_Service EMP_Code EMP_dept
a 30 6 c264 xyz
b 29 3 f367 abc
r 27 1 g364 lmn
d 45 10 c264 abc
t 50 25 t453 lmn
我想使用 file1 中的所有 EMP_Code 值從 master_file 中提取類似的行。我嘗試了以下代碼,但丟失了很多資料。我無法讀取完整的主 csv 檔案,因為它大約 20gb,有數百萬行并且記憶體不足。我想分塊讀取 master_file 并提取 file1 中存在的每個 EMP_Code 的完整行并將其保存到新檔案 Employee_full_data 中。
import csv
import pandas as pd
df = pd.read_csv(r"master_file.csv")
li = [c264,f367]
full_data = df[df.EMP_Code.isin(li)]
full_data.to_csv(r"Employee_full_data.csv", index=False)`
我還嘗試了以下代碼。每當我使用 EMP_Code 列時,我都會收到一個空檔案,而當我使用 Emp_name 或 EMP_dept 等列時,我可以正常作業。我想使用 EMP_Code 提取資料。
import csv
import pandas as pd
df = pd.read_csv(r"file1.csv")
list_codes = list(df.EMP_Code)
selected_rows = []
with open(r"master_file.csv") as csv_file:
reader = csv.DictReader(csv_file)
for row in reader:
if row['EMP_Code'] in list_codes:
selected_rows.append(row)`
article_usage = pd.DataFrame.from_records(selected_rows)
article_usage.to_csv(r"Employee_full_data.csv", index=False)
有沒有其他方法可以無損提取資料?我聽說過分塊連接和讀取資料,但不知道如何在這里使用它。任何幫助表示贊賞
uj5u.com熱心網友回復:
您只需傳遞chunksize=<SOME INTEGER>給 pandas 的 .read_csv 函式(請參閱此處的檔案)
如果您傳遞 a chunksize=2,您會將檔案讀入 2 行的資料幀。或者......更準確地說,它會將 2 行 csv 讀入資料幀。然后,您可以將過濾器應用于該 2 行資料幀并將其“累積”到另一個資料幀中。下一次迭代將讀取接下來的兩行,您可以隨后對其進行過濾... 起泡、沖洗并重復:
import pandas as pd
li = ['c264', 'f367']
result_df = pd.DataFrame()
with pd.read_csv("master_file.csv", chunksize=2) as reader:
for chunk_df in reader:
filtered_df = chunk_df[chunk_df.EMP_Code.isin(li)]
result_df = pd.concat([result_df, filtered_df])
print(result_df)
# Outputs:
# EMP_name EMP_age EMP_Service EMP_Code EMP_dept
# 0 a 30 6 c264 xyz
# 1 b 29 3 f367 abc
# 3 d 45 10 c264 abc
uj5u.com熱心網友回復:
您可以修復這些型別的檔案讀/寫任務的一種方法是使用生成器并以您可以處理的塊或部分(記憶體或其他限制)讀取您想要的資料。
def read_line():
with open('master_file.csv','r') as fid:
while (line:= fid.readline().split()):
yield line
這個簡單的生成器在每次呼叫中都會給出一個新行。現在你可以簡單地迭代它來做你感興趣的過濾并構建你的新資料框。
r_line = read_line()
for l in r_line:
print(l)
您可以將生成器修改為例如決議和回傳串列,或多行等。
uj5u.com熱心網友回復:
我在您的小示例上運行了您的第二個示例(使用 csv.DictReader)中的代碼并且它有效。我猜你的問題可能與你提到的 master_file 的真實規模有關。
問題可能是盡管使用 csv.DictReader 將資訊流式輸入,但您仍在使用 Pandas 資料框在寫出之前聚合所有內容,并且輸出可能會超出您的記憶體預算。
如果是這樣,則使用 csv.DictWriter 流式傳輸。唯一棘手的一點是設定寫入器,因為它需要知道欄位名,在我們讀取第一行之前無法知道,所以我們將在讀取回圈的第一次迭代中設定寫入器。
(我洗掉了with open(...背景關系,因為我認為它們添加了太多縮進)
df = pd.read_csv(r"file1.csv")
list_codes = list(df.EMP_Code)
f_in = open(r"master_file.csv", newline="")
reader = csv.DictReader(f_in)
f_out = open(r"output.csv", "w", newline="")
init_writer = True
for row in reader:
if init_writer:
writer = csv.DictWriter(f_out, fieldnames=row)
writer.writeheader()
init_writer = False
if row["EMP_Code"] in list_codes:
writer.writerow(row)
f_out.close()
f_in.close()
| EMP_name | EMP_age | EMP_Service | EMP_代碼 | EMP_部門 |
|---|---|---|---|---|
| 一個 | 30 | 6 | c264 | xyz |
| b | 29 | 3 | f367 | 美國廣播公司 |
| d | 45 | 10 | c264 | 美國廣播公司 |
如果您想完全擺脫 Pandas:
list_codes = set()
with open(r"file1.csv", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
list_codes.add(row["EMP_Code"])
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/520930.html
標籤:PythonCSV
