Saving list to a .csv file - python-3.x

I have made a code that opens a .csv file and takes a user input to filter it to a new list. What I am having trouble with is saving this new list to a .csv file properly.
This is my code:
#author: Joakim
from pprint import pprint
import csv
with open ('Change_in_Unemployment_2008-2014.csv') as csvfile:
readCSV = csv.reader(csvfile, delimiter=',')
next(readCSV) #Removing header
result = []
found = False
user_input = input("Please enter a full/partial NUTS code to filter by: ")
for row in readCSV:
if row[0].startswith(user_input):
result.append(row)
found = True
if found == False:
print("There are no registered NUTS codes containing your input.. Please try again")
if found == True:
print("\n Successfully found ", len(result), "entries!""\n")
pprint (result)
#store data in a new csv file
Stored_path = "C:\data_STORED.csv"
file = open(Stored_path, 'w')
writer = csv.writer(file)
writer.writerow(["NUTS CODE", " Municipality", " value"])
for i in range(len(result)):
new_row = result[i]
NUTS_CODE = new_row[0]
Municipality = new_row[1]
Value = new_row[2]
writer.writerow([NUTS_CODE, Municipality])
csvfile.close()
If one runs my code with an input of : PL, one gets this list:
[['PL11', 'odzkie', '2.2'],
['PL12', 'Mazowieckie', '1.2'],
['PL21', 'Maopolskie', '2.9'],
['PL22', 'Slaskie', '2'],
['PL31', 'Lubelskie', '1.1'],
['PL32', 'Podkarpackie', '5.8'],
['PL33', 'Swietokrzyskie', '2.6'],
['PL34', 'Podlaskie', '2.7'],
['PL41', 'Wielkopolskie', '1.6'],
['PL42', 'Zachodniopomorskie', '-1.1'],
['PL43', 'Lubuskie', '1.8'],
['PL51', 'Dolnoslaskie', '0'],
['PL52', 'Opolskie', '1.3'],
['PL61', 'Kujawsko-Pomorskie', '1.6'],
['PL62', 'Warminsko-Mazurskie', '2.4'],
['PL63', 'Pomorskie', '3.1']]'
Now I would like to store this neatly into a new .csv file, but when I use the code above, I only get a couple of values repeated throughout.
What is my error?

Related

When editing data in a CSV how do you exclude/only include certain columns?

I've got a CSV of client details for a bank project in Python 3. I've managed to create a function in which you can edit the client details but I want to exclude the last 2 columns as and and can't figure out how.
Example of CSV data:
first_name,last_name,title,pronouns,dob,occupation,account_balance,overdraft_limit
Garner,Coupman,Ms,Male,14/04/2022,General Manager,2200.76,2.28
Jens,Eldrid,Honorable,Male,13/11/2021,Research Associate,967.64,79.15
Edit function:
if choice == "4":
editClient = int(input("Please enter the index number of the client you wish to edit: "))
print("Please enter the details for each of the following: ")
for i in range(len(existing_clients[0])):
newDetails = input("Enter new data for " + str(existing_clients[0][i]) + ": ")
existing_clients[editClient][i] = newDetails
changes = input("Are you sure you'd like to make these changes? Enter Yes or No")
if changes == ("Yes"):
# Newline fixed the spacing issue I was having
with open("mock_data.csv", "w+", newline="") as file:
reader = csv.writer(file)
for i in range(len(existing_clients)):
reader.writerow(existing_clients[i])
if changes == ("No"):
exit()
I've tried changing
for i in range(len(existing_clients[0])):
to
for i in range(len(existing_clients[0:6])):
and I thought this worked until I tried editing a client later the row 6.
I've also messed around a lot with
newDetails = input("Enter new data for " + str(existing_clients[0][i]) + ": ")
to no avail.
Edit the row with slicing and exclude the last two columns:
with open("mock_data.csv", "w", newline="") as file:
writer = csv.writer(file)
for client in existing_clients:
writer.writerow(client[:-2]) # exclude last two columns
Working example with data:
input.csv
first_name,last_name,title,pronouns,dob,occupation,account_balance,overdraft_limit
Garner,Coupman,Ms,Male,14/04/2022,General Manager,2200.76,2.28
Jens,Eldrid,Honorable,Male,13/11/2021,Research Associate,967.64,79.15
test.py
import csv
with open('input.csv', newline='') as f:
reader = csv.reader(f)
data = list(reader)
with open('output.csv', 'w', newline='') as f:
writer = csv.writer(f)
for line in data:
writer.writerow(line[:-2])
output.csv
first_name,last_name,title,pronouns,dob,occupation
Garner,Coupman,Ms,Male,14/04/2022,General Manager
Jens,Eldrid,Honorable,Male,13/11/2021,Research Associate
To select specific columns, you could concatenate different slices:
writer.writerow(line[:2] + line[5:6]) # column indexes 0, 1, and 5
Or use DictReader/DictWriter:
import csv
with open('input.csv', newline='') as f:
reader = csv.DictReader(f)
data = list(reader)
with open('output.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['last_name', 'occupation'], extrasaction='ignore')
writer.writeheader()
for line in data:
writer.writerow(line)
output.csv
last_name,occupation
Coupman,General Manager
Eldrid,Research Associate

Writing new rows into CSV

Im not a dedicated programmer and its my first time doing a thing like this.
I made a While loop which uses entries that would be written into a CSV file.
I dont know how to repeat the loop so new values would be written into the new rows in alphabetical order.
I managed to make this program that works, but only has a one time entry into a one single row. Every time you would restart the program and enter something new it would override the old data row in CSV.
import csv
fields = ['Name', 'Surname', 'Status']
rows = [[]]
while True:
status=input("Enter status number: ")
if status !="3":
print("Wrong status number.")
else:
surname=input("Enter surname: ")
name=input("Enter name: ")
value=surname+"-"+name+"-"+name+"."+surname+"#mail.com"+","+status
print(value)
value=name+","+surname+","+name+"."+surname+"#mail.com"+","+status
for inner_row in rows:
_name=name
_surname=surname
_name_surname=name+"."+surname+"#mail.com"
rows[0].append(_name)
rows[0].append(_surname)
rows[0].append(_name_surname)
rows[0].append(status)
break
filename = "university_records.csv"
with open(filename, 'w') as csvfile:
csvwriter = csv.writer(csvfile)
csvwriter.writerow(fields)
csvwriter.writerows(rows)
To not overwrite the data everytime you run the program, you can simply change the w to an a in the with-context manager:
with open(filename, "a") as csvfile:
The "w" is for write, the "a" is for append
Howver, you are writing the fields (name, surname etc) everytime you run the program as well, this you can fix with a simple if-statement. the file-object (csvfile) has a method called tell() which returns the position of the cursor in the file-object. If the position is 0, the file is new and you print the fields. Else you skip it
if csvfile.tell() == 0:
csvwriter.writerow(fields)
I also think you are missing a field for the file to be a correct csv-file.
fields = ['Name', 'Surname', 'email', 'Status']
Hope this helped
import csv
import os
fields = ['Name', 'Surname', 'Email', 'Status']
filename = "university_records.csv"
rows = []
if os.path.isfile(filename):
with open(filename) as csv_file:
csv_reader = csv.reader(csv_file)
next(csv_reader) # skip header
for row in csv_reader:
rows.append(row)
while True:
status = input("Enter status number (or 'exit' to exit): ")
if status == "exit":
break
if status != "3":
print("Wrong status number.")
else:
surname = input("Enter surname: ")
name = input("Enter name: ")
email = name + "." + surname + "#mail.com"
rows.append([name, surname, email, status])
with open(filename, 'w') as csv_file:
csv_writer = csv.writer(csv_file)
csv_writer.writerow(fields)
csv_writer.writerows(sorted(rows))
Thanks for the help guys. I had this assignment so I didn't want to 100% "cheat" as copy pasting your code. So I mixed a bit of both, up to the point where I could explain what is happening in the code.
Best regards!

How to import a specific Key with its values in a csv file using Python?

In my program, the user will enter a country name and my code will first whether or not the country name exists in the dictionary. If it exists, the code has to print the country name and its associated values in a csv file. However, I am unable to do the csv part. I have presented the dictionary and relevant code for this issue. Kindly let me know what the issue is.
import string
import re
import csv
data = {
"Pakistan": (0.57, 0.05, 0.79),
"India": (0.47, 0.12, 0.54),
"Bangladesh": (0.49, 0.17, 0.81)
}
csv_columns = ['Country Name','1997','1998','1999','2000','2001','2002','2003','2004','2005','2006','2007','2008','2009','2010']
csv_file = "Emissions_subset.csv"
con_name = input("Write up to three comma-separated countries for which you want to extract data: ")
count = len(re.findall(r'\w+', con_name))
if count == 1:
con_check1 = con_name.split()[0]
if con_check1.lower() in map(str.lower, data.keys()):
with open(csv_file, 'w') as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=csv_columns)
writer.writeheader()
writer.writerow(list(data.keys()).index(con_check1))
print("Data successfully extracted for countries {} saved into file Emissions_subset.csv".format(con_check1.capitalize()))

How to add headers when creating csv file in python

I am getting "raw" data from a csv file, and putting only what I need for a new csv file that will be used to auto add users to a different system...
I am unsure how to add the correct headers needed for the file.
I've tried looking at other examples of adding headers but have not figured this out yet...
The headers I need to add are as follows:
"ID Card Number","Name","E-Mail","User Level","Position","Status","Covered Under Insurance","Paid Insurance"
(and in that order)
import csv
def studentscsv():
with open('..\StudentEmails_and_StudentNumbers.csv') as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',')
with open('mydirectory\student_users.csv', mode='w', newline='') as output_file:
write = csv.writer(output_file, delimiter=',', quoting=csv.QUOTE_MINIMAL)
for row in csv_reader:
a = row[0]
studentnumber = row[1]
firstname = row[2]
lastname = row[3]
grade = row[4]
studentname = firstname + " " + lastname
studentemail = firstname + "." + lastname + "#mydomain.org"
status = "Active"
position = "Student"
covered = "Yes"
paid = "Yes"
write.writerow([studentnumber, studentname, studentemail, grade, position, status, covered, paid])
def main():
"""
Controls the program execution
:param in_file: the name of the input file.
:return: None
"""
if __name__ == '__main__':
main()
The file generates fine with the way the code is written. I am just unsure what I need to change to add the headers.
Using the csv module, as you are, it's pretty straight forward. Define your headers in an array and then create a DictWriter with the fieldnames set to your array. Reference the following code and documentation:
import csv
with open('names.csv', 'w') as csvfile:
fieldnames = ['first_name', 'last_name']
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'})
writer.writerow({'first_name': 'Lovely', 'last_name': 'Spam'})
writer.writerow({'first_name': 'Wonderful', 'last_name': 'Spam'})
Here's the documentation:
https://docs.python.org/2/library/csv.html#csv.DictWriter

Python file write issue with Pandas

i wrote this python script to search for unseen mail in a mailbox, download xlsx attachment, make some modification on it and then post them to another service.
All is working perfect with just one issue:
In the original xlsx file there is a column named "zona" containing the italian two letter string for the province.
If this value is "NA" (the value of the province of NAPLES) when
saving the resultant xlsx files has blank cell instead of NA.
is NA a reserved word and if yes, there is a way to quote it?
import os,email,imaplib,socket,requests
import pandas as pd
mail_user = os.environ.get('MAIL_USER')
mail_password = os.environ.get('MAIL_PASS')
mail_server = os.environ.get('MAIL_SERVER')
detach_dir = '.'
url=<removed url>
if mail_user is None or mail_password is None or mail_server is None:
print ('VARIABILI DI AMBIENTE NON DEFINITE')
exit(1)
try:
with imaplib.IMAP4_SSL(mail_server) as m:
try:
m.login(mail_user,mail_password)
m.select("INBOX")
resp, items = m.search(None, "UNSEEN")
items = items[0].split()
for emailid in items:
resp, data = m.fetch(emailid, "(RFC822)")
email_body = data[0][1] # getting the mail content
mail = email.message_from_bytes(email_body) # parsing the mail content to get a mail object
if mail.get_content_maintype() != 'multipart':
continue
for part in mail.walk():
if part.get_content_maintype() == 'multipart':
continue
if part.get('Content-Disposition') is None:
continue
filename = part.get_filename()
if filename.endswith('.xlsx'):
att_path = os.path.join(detach_dir, filename)
fp = open(att_path, 'wb')
fp.write(part.get_payload(decode=True))
fp.close()
xl = pd.ExcelFile(att_path)
df1 = xl.parse(sheet_name=0)
df1 = df1.replace({'\'':''}, regex=True)
df1.loc[df1['Prodotto'] == 'SP_TABLETA_SAMSUNG','Cod. ID.'] = 'X'
df1.loc[df1['Prodotto'] == 'AP_TLC','Cod. ID.'] = 'X'
df1.loc[df1['Prodotto'] == 'APDCMB00003','Cod. ID.'] = 'X'
df1.loc[df1['Prodotto'] == 'APDCMB03252','Cod. ID.'] = 'X'
writer = pd.ExcelWriter(att_path, engine='xlsxwriter')
df1.to_excel(writer, sheet_name='Foglio1', index=False)
writer.save()
uf = {'files': open(att_path, 'rb')}
http.client.HTTPConnection.debuglevel = 0
r = requests.post(url, files=uf)
print (r.text)
except imaplib.IMAP4_SSL.error as e:
print (e)
exit(1)
except imaplib.IMAP4.error:
print ("Errore di connessione al server")
exit(1)
It seems that Pandas is treating the NA value as a NaN and therefore, when you write to excel it writes this value as '' by default (see docs).
You can pass na_rep='NA' to the to_excel() function in order to write it out as a string;
df1.to_excel(writer, sheet_name='Foglio1', index=False, na_rep='NA')
But as a precaution keep an eye out as any other NaN values present in your df will also be written to the excel file as 'NA'.
Reading the docs link post by #Matt B. i found this solution:
df1 = xl.parse(sheet_name=0, keep_default_na=False, na_values=['_'])
If i understand well only _ are interpreted as "not avalaible"

Resources