0

I'm a noob here and I have pretty straight forward question with writing CSV output files with Python. I've been googling this for a while and I can't find an answer to my q. I have a bunch of tasks which have to output answers to the terminal as well as write the answers to a CSV output file. I've got all the correct answers in the terminal but I can't figure out how to write them to a CSV file. My print statements contain variables, and I need the value of the variable printed. I.E. "The total profit/loss for this period is: $22564198" should be printed to the CSV not the print statement format which is: 'The total profit/loss for this period is: ${total}'

I'm copying my code below.

import os 
import csv

date = []
profloss = []
changes = []
total = 0
totalChange = 0 
mo2mo = {}


budget_csv = os.path.join(xxxxxx)

with open(budget_csv) as csvfile:
    csvreader = csv.reader(csvfile, delimiter=",")

#splitting the two columns into seperate lists
    for row in csvreader:
        date.append(row[0])
        profloss.append(row[1])
    
#removing header rows
    date.pop(0)
    profloss.pop(0)

#printing how many months are in the data set
    dataLen = len(date)
    countMonths = "This data set has " + str(len(date)) + " months." 
    
#calculating total profit/loss
    for i in range(0, len(profloss)):
        profloss[i] = int(profloss[i])
        total = total + (profloss[i])
    print(f'The total profit/loss for this period is: ${total}')

#calculating the difference between months and adding it to a list
    for i in range(0, len(profloss)-1):
        difference = (profloss[i+1]) - (profloss[i])
        changes.append(difference)

#removing the first element in date to make a dictionary for dates: changes
    date.pop(0)
    
#creating a dictionary of months as keys and change as values, starting with the second month
    mo2mo = {date[i]: changes[i] for i in range(len(date))}
   
#calculating the average change from one month to the next
    
    for i in range(0, len(changes)):
        totalChange = totalChange + changes[i] 
    avChange = totalChange/len(changes)
    print(f'The average change from month to month for this dataset is: {round((avChange),2)}')

#getting the month with the maximum increase
    keyMax = max(mo2mo, key= lambda x: mo2mo[x])

    for key,value in mo2mo.items():
        if key == keyMax:
            print(f'The month with the greatest increase was: {key} ${value}')
    

#getting the month with the maximum decrease
    keyMin = min(mo2mo, key= lambda x: mo2mo[x])
    for key, value in mo2mo.items():
        if key == keyMin:
            print(f'The maximum decrease in profits was: {key} ${value}')
    

outputCSV = ("countMonths",)
output_path = os.path.join("..", "output", "PyBankAnswers.csv")
#writing outcomes to csv file
with open(output_file,"w") as datafile:
    writer = csv.writer(datafile)
    for row in writer.writerow()

I've only got experience printing whole lists to csv files and not actual statements of text. I've tried to find how to do this but I'm not having luck. There's got to be a way without me just writing out the sentence I want printed by hand and having the CSV writer print that statement? OR do I just have to copy the sentence from the terminal and then print those statements row by row?

11
  • for row in writer.writerow() doesn't make any sense. You need to loop over the rows in your list, then call writer.writerrow() on each row. Commented Dec 24, 2022 at 20:19
  • What do you want the CSV to look like? Are you hoping to modify the CSV you are reading? Commented Dec 24, 2022 at 20:19
  • Yeah my write statement is incomplete, as I'm not sure what to do with it yet, thats my question for you fine folks. Commented Dec 24, 2022 at 20:20
  • Tim- the CSV should just have the same lines of text that would be printed to the console. The total profit/loss for this period is: $22564198 The average change from month to month for this dataset is: -8311.11 The month with the greatest increase was: Aug-16 $1862002 The maximum decrease in profits was: Feb-14 $-1825558 Commented Dec 24, 2022 at 20:21
  • That's not a CSV file, it's just an ordinary text file. Commented Dec 24, 2022 at 20:21

1 Answer 1

2

The print() function accepts a file option to specify that the output should be written to an open file stream. So you can make all your print() statements twice, once to the terminal and then to the file. To avoid all this duplication, you can put that into a function. Then call that instead of print() everywhere.

import os 
import csv

date = []
profloss = []
changes = []
total = 0
totalChange = 0 
mo2mo = {}

def print_to_terminal_and_file(f, *args, **kwargs):
    print(*args, **kwargs)
    print(*args, file=f, **kwargs)

budget_csv = os.path.join(xxxxxx)

with open(budget_csv) as csvfile:
    csvreader = csv.reader(csvfile, delimiter=",")

    #splitting the two columns into seperate lists
    for row in csvreader:
        date.append(row[0])
        profloss.append(int(row[1]))
    
#removing header rows
date.pop(0)
profloss.pop(0)

output_path = os.path.join("..", "output", "PyBankAnswers.txt")
#writing outcomes to text file
with open(output_file,"w") as datafile:

    #printing how many months are in the data set
    print_to_terminal_and_file(datafile, f"This data set has {len(date)} months.")

    #calculating total profit/loss
    total = sum(profloss)
    print_to_terminal_and_file(datafile, f'The total profit/loss for this period is: ${total}')

    #calculating the difference between months and adding it to a list
    for i in range(0, len(profloss)-1):
        difference = (profloss[i+1]) - (profloss[i])
        changes.append(difference)

    #removing the first element in date to make a dictionary for dates: changes
    date.pop(0)

    #creating a dictionary of months as keys and change as values, starting with the second month
    mo2mo = {date[i]: changes[i] for i in range(len(date))}

    #calculating the average change from one month to the next

    for i in range(0, len(changes)):
        totalChange = totalChange + changes[i] 
    avChange = totalChange/len(changes)
    print_to_terminal_and_file(datafile, f'The average change from month to month for this dataset is: {round((avChange),2)}')

    #getting the month with the maximum increase
    keyMax = max(mo2mo, key= lambda x: mo2mo[x])

    for key,value in mo2mo.items():
        if key == keyMax:
            print_to_terminal_and_file(datafile, f'The month with the greatest increase was: {key} ${value}')


    #getting the month with the maximum decrease
    keyMin = min(mo2mo, key= lambda x: mo2mo[x])
    for key, value in mo2mo.items():
        if key == keyMin:
            print_to_terminal_and_file(datafile, f'The maximum decrease in profits was: {key} ${value}')
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks so much. I'm studying your answer as I haven't learned *args, **kwargs yet, but I googled it and understand it. I had to add a return statement to your function as I was getting errors without it. Would you mind explain how file=f works in your function? Thats the only thing I'm confused about.
file=f is an optional keyword argument for print(). When provided, assuming f is an open file stream, print will "print" to the file stream. In this case, you provide datafile as the open filestream (you opened this file yourself with the line with open(output_file,"w") as datafile:. So that's really it. It just so happened that the parameter is called f because that's how the method was written, with f in the first position: def print_to_terminal_and_file(f, *args, **kwargs): ... so datafile is the name of the filestream in your script, but it has the name f in the function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.