2017-03-29 29 views
3

這裏是我的CSV文件的內容的一個示例:的Python:在for循環,尤其是列有條件地將值寫入CSV

Fruit, colour, ripe, 

apple, green,, 
banana, yellow,, 
pineapple, green,, 
plum, purple,, 

我想通過CSV文件的內容和環根據測試(外在的CSV數據,利用提供給它的函數的輸入值),結束了這樣的事:

Fruit, colour, ripe, 

apple, green, true, 
banana, yellow,, 
pineapple, green,, 
plum, purple, true, 

我當前的代碼看起來是這樣的:

csv_data = csv.reader(open('./data/fruit_data.csv', 'r')) 
for row in csv_data: 
    fruit = row[0] 
    if fruit == input: 
    # Here, write 'true' in the 'ripe' column. 

使用CSV模塊或pandas一次性添加新數據很容易,但在這裏我需要迭代地添加數據。似乎我無法在適當的位置更改CSV文件(?),但是如果我寫出一個不同的CSV文件,它將覆蓋循環中的每個匹配項,因此它只會反映該值。

+0

你需要像'csv_data.write(行+「成熟」)' –

+0

它始終是建議創建一個新的文件,而不是覆蓋。 –

回答

3

你有,基本上,有兩種方法:

1-打開第二個文本文件,你的循環之前,然後通過初始文件中的每一行循環,並追加行的第二個文件。所有行完成後,關閉最初的文件。例如:How do you append to a file?

2-從最初的csv中讀入所有內容。然後對你創建的對象進行更改(我強烈建議使用Pandas)。然後寫出一個csv。下面是該方法的一個示例:

import pandas as pd 
import numpy as np 

# read in the csv 
csv_data = pd.read_csv('./data/fruit_data.csv') 

# I'm partial to the numpy where logic when creating a new column based 
# on if/then logic on an existing column 
csv_data['ripe'] = np.where(csv_data['fruit']==input, True, False) 

# write out the csv 
csv_data.to_csv('./data/outfile.csv') 

1和2之間的選擇實際上應該按比例縮放。如果你的csv太大,你不能全部閱讀並按你想要的方式操作它,那麼你應該逐行掃描它。如果你可以讀完所有的東西,然後用熊貓來操作它,你的生活將會變得更加容易。

+1

這些不是超大文件,所以我可能會考慮選項二。如果我理解正確:使用[pandas.read_csv](http://pandas.pydata.org/pandas-docs/stable/generated/pandas.read_csv.html#pandas.read_csv)讀出原始文件,處理數據幀,然後用[pandas.DataFrame.to_csv]寫出來(http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_csv.html)? – arokath

+0

我添加了第二個選項的示例,顯示使用熊貓讀入和讀出數據。我不確定你的邏輯是否適合'熟化' –

+0

我非常喜歡這種方法,非常優雅。我非常感謝額外的幫助。非常感謝! – arokath

1

爲了進行更改,您必須將新數據添加到列表等位置。該列表將包含您的處理結果。

fruit_details= list() 
csv_data = csv.reader(open('./data/fruit_data.csv', 'r')) 
for row in csv_data: 
    fruit = row[0] 
    if fruit == input: 
     fruit_details.append([row[0],row[1],'true']) 

結果列表fruit_details將在「熟」列中包含true的果實。如果你添加一個非水果項目,添加和else語句,根據需要放置false或row [2]。

+0

你的意思是「真」嗎? – 9000

+0

我最終做了一點不同,但我喜歡使用列表的想法,並會玩這個方法。非常感謝您的幫助! – arokath

1

如果您創建一個臨時文件,您可以在讀取它們時編寫行。如果你在Unix上,「the renaming will be an atomic operation」使用os.rename

import csv 
import os 

def update_fruit_data(input): 
    csv_file_name = 'data/fruit_data.csv' 
    tmp_file_name = "%s.tmp" % csv_file_name 
    # Update fruit data 
    with open(csv_file_name, 'r') as csv_input_file: 
     csv_reader = csv.reader(csv_input_file) 
     with open(tmp_file_name, 'w') as csv_output_file: 
      csv_writer = csv.writer(csv_output_file) 
      for row in csv_reader: 
       fruit = row[0] 
       if fruit == input: 
        row[2] = 'true' 
       csv_writer.writerow(row) 
    # Rename tmp file to csv file 
    os.rename(tmp_file_name, csv_file_name) 

while True: 
    input = get_input() 
    update_fruit_data(input) 

這裏get_input是替身不管你用得到的input值。

+0

謝謝,我最終以不同的方式做了這件事,但我將來會回顧一下。 – arokath

1

如果你想創建一個新的CSV文件

csv_data = csv.reader(open('./Desktop/fruit_data.csv', 'r')) 
csv_new = csv.writer(open('./Desktop/fruit_new_data.csv', 'w')) 
for row in csv_data: 
    fruit = row[0] 
    if fruit == input: 
     row.append("ripe") 
     csv_new.writerow(row) 
    else: 
     csv_new.writerow(row) 

基本上在你前面的問題唯一缺少的是最後statment,這是寫的,別人是在案件中添加的標準不匹配。

另一種可能是使用linestartswith

+0

這工作完美。非常感謝你! – arokath