Write csv with each list as column - python

I have a dictionary that holds a two level nested list for each key that looks like the following:
OrderedDict([(0,[['a','b','c','d'],['e','f','g','h']]), (1,[['i','j','k','l'],['m','n','o','p']])])
I would like to write each nested list to a csv as a column:
a,b,c,d e,f,g,h
i,j,k,l m,n,o,p
the output I am getting from my current code is:
['a','b','c','d'] ['e','f','g','h']
['i','j','k','l'] ['m','n','o','p']
The columns are correct but I would like to remove the brackets [ ] and quotes ' '
a,b,c,d e,f,g,h
i,j,k,l m,n,o,p
CODE:
with open('test.csv', 'w', newline='') as csv_file:
writer = csv.writer(csv_file, quotechar='"', quoting=csv.QUOTE_ALL)
for record in my_dict.values():
writer.writerow(record)
Any help would be appreciated!

This should work:
with open('test.csv', 'w', newline='') as csv_file:
writer = csv.writer(csv_file, quotechar='"', quoting=csv.QUOTE_ALL)
for record in my_dict.values():
final = [",".join(index) for index in record]
writer.writerow(final)

I am having trouble visualizing how your record looks because it seems like each value should be a nested list, meaning each column should contain both lists. If it were really writing one value from .values() at a time, it seems like you would get one column with both lists in it.
At any rate, what you want to achieve should probably be sought through the .join() method:
for record in my_dict.values():
writer.writerow(','.join(record))
But the thing is, you're making a CSV (comma separated values) file, so each comma may be interpreted as a field-delimiter.
Question: Have you considered using a different delimiter when you instantiate your csv.writer?

Related

How to arrange data in the source order after using csv.DictReader()?

I'm trying to convert a csv file into a dictionary for calculation purposes and print it in exactly the same order (e.g. a, b, c, d, etc.) as they were in the original csv file.
I just learnt and tried using csv.DictReader(file) but I realized every time I did a print, the sequence of the row, column keeps changing, or I would say it mess up randomly.
Any solution for this or is there any part I did wrong?
import csv
with open("breast_cancer_v1.csv", 'r') as file:
csv_file = csv.DictReader(file)
for row in csv_file:
print(dict(row))
I had name my column header as "a, b, c ,d ,e ,f ,h, i, j, k, l, m" inside my csv but the print sequence mess up as below:
output
notice the dictionary keys are not in order and my rows are also facing the same problem if i have too many rows in the csv (e.g. 100+ rows)
My original csv data looks like this:
Or if you really want to print it as a dictionary, then you have to give each column a name with the fieldnames option:
import csv
with open("artist.csv", newline='') as file:
fieldnames = ['first_col', 'sec_col',...,'last_col']
csv_file = csv.DictReader(file, fieldnames=fieldnames)
for row in csv_file:
print(row)
The order you list the fieldnames in will be the order they appear in. You'll have to remove the original column header in your csv file.
if you want to print in order just use this:
import csv
with open("breast_cancer_v1.csv", 'r') as file:
for row in file:
print(row)

Sort CSV File by Numerical Values

So for a Homework task i have to make a program that sorts scores like a leader board and i cant figure out how to sort it in descending order.
I will send the rest of my code if that helps, any help would be appreciated.
Forgot to mention CSV file looks like this:
NAME, SCORE
I have Seen many questions on here about this and none of them seem to work with mine.
with open('names.csv', 'a', newline='') as names:
csvWriter = csv.writer(names)
csvWriter.writerow([name, int(score)])
with open('names.csv', 'r') as names:
csvReader = csv.reader(names)
csv1 = csv.reader(names, delimiter='.')
sort = sorted(csv1, key=operator.itemgetter(0))
csv_writer = csv.writer(names, delimiter='.')
for name in csvReader:
print(' '.join(name))
no error message or results, just an exit code
See here for reading a csv into dataframe
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html
and here for sorting it
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.sort_values.html
There's a few problems with your code here, i'll try to break it down.. I don't recommend you jump to pandas just yet. I'm going to assume this is actually writing data.. but you should check "names.csv" to make sure it isn't empty. It looks like this would only write one row. I'm also not sure why you set newline='', I probably wouldn't do that here.. though i'm not sure it will matter to csv.writer.
with open('names.csv', 'a', newline='') as names:
csvWriter = csv.writer(names)
csvWriter.writerow([name, int(score)])
usually you would have a loop inside a statement like this:
my_list = [("Bob", "2"), ("Alice", "1")]
with open('names.csv', 'a') as names:
csvWriter = csv.writer(names)
for name, score in my_list:
csvWriter.writerow([name, int(score)])
You make two csv readers here.. i'm not sure why. The second one uses "." as it's delimiter.. you haven't specified a delimiter when you wrote the csv, so it would actually have the standard delimiter with is a comma ",". csvReader would use this by default, but csv1 will attempt to split on periods and not do so well.
with open('names.csv', 'r') as names:
csvReader = csv.reader(names)
csv1 = csv.reader(names, delimiter='.')
You shouldn't use "sort" as a variable name.. it's the name of a common method. But that won't actually break anything here.. you create a new sorted version of csv1 but you actually run your for loop on csvReader which hasn't changed since you set it above. You also create csv_writer with names with is open for reading, not writing. but you don't use it anyway.
itemgetter is looking at index 0, which would be the names from your writer.. if you want to sort by score use 1.
sort = sorted(csv1, key=operator.itemgetter(0))
csv_writer = csv.writer(names, delimiter='.')
for name in csvReader:
print(' '.join(name))
I think this might be more what you're going for.. with my example list.
#!/usr/bin/env python3
import csv
import operator
my_list = [("Bob", "2"), ("Alice", "1")]
with open('names.csv', 'a') as names:
csvWriter = csv.writer(names)
for name, score in my_list:
csvWriter.writerow([name, int(score)])
with open('names.csv', 'r') as names:
csvReader = csv.reader(names)
sorted_reader = sorted(csvReader, key=operator.itemgetter(1))
for name, score in sorted_reader:
print(name, score)
Output:
Alice 1
Bob 2
Since you want it to look "like a leaderboard" you probably want a different sort though.. you want to reverse it and actually use the integer values of the score column (so that 100 will appear above 2, for example).
sorted_reader = sorted(csvReader, key=lambda row: int(row[1]), reverse=True)

Python: adding the same string to the end of each row

I'm modifying a CSV file with two fieldnames and I would like to add a string to the end of each row under an additional fieldname. I've figured out how to add the fieldname, but not how to add things to it. It seems like it should be simple, but I'm stumped.
import csv
with open('test2l.csv', 'r') as inny:
reader = csv.DictReader(inny)
with open('outfile.csv', 'w') as outty:
fieldnames = ["Genus", "Species", "Source"]
writer = csv.DictWriter(outty, fieldnames = fieldnames)
writer.writeheader()
for record in reader:
g = record['Genus']
s = record['Species']
Everything I tried has just added the string to the existing string in 'Species' and I haven't been able to create a record for 'Source', I assume because it's empty.
Thanks!
If you haven't already, check out the documentation for csv.Reader, csv.DictReader, and csv.DictWriter.
The documentation indicates that reader objects operate on an on object using the iterator protocol. Iterating once (for row in reader:, for example) to add a "Source" exhausts the underlying iterator. Attempting to then use the same reader with a writer later would not work.
To work around this, you could create a list:
rows = list(csv.DictReader(inny))
While this exhausts the iterator, you now have a list to work with. However, this might not be ideal if the list is very long.
Another solution would be to add the Source and write the row during the same iteration:
for row in reader:
row['Source'] = 'same string every time'
writer.writerow(row)
Simply write:
for record in reader:
record["Source"] = "whateversource"
And do so before the step where you are writing to a file.`

Sorting a table in python

I am creating a league table for a 6 a side football league and I am attempting to sort it by the points column and then display it in easygui. The code I have so far is this:
data = csv.reader(open('table.csv'), delimiter = ',')
sortedlist = sorted(data, key=operator.itemgetter(7))
with open("Newtable.csv", "wb") as f:
fileWriter = csv.writer(f, delimiter=',')
for row in sortedlist:
fileWriter.writerow(row)
os.remove("table.csv")
os.rename("Newtable.csv", "table.csv")
os.close
The number 7 relates to the points column in my csv file. I have a problem with Newtable only containing the teams information that has the highest points and the table.csv is apparently being used by another process and so cannot be removed.
If anyone has any suggestions on how to fix this it would be appreciated.
If the indentation in your post is actually the indentation in your script (and not a copy-paste error), then the problem is obvious:
os.rename() is executed during the for loop (which means that it's called once per line in the CSV file!), at a point in time where Newtable.csv is still open (not by a different process but by your script itself), so the operation fails.
You don't need to close f, by the way - the with statement takes care of that for you. What you do need to close is data - that file is also still open when the call occurs.
Finally, since a csv object contains strings, and strings are sorted alphabetically, not numerically (so "10" comes before "2"), you need to sort according to the numerical value of the string, not the string itself.
You probably want to do something like
with open('table.csv', 'rb') as infile:
data = csv.reader(infile, delimiter = ',')
sortedlist = [next(data)] + sorted(data, key=lambda x: int(x[7])) # or float?
# next(data) reads the header before sorting the rest
with open("Newtable.csv", "wb") as f:
fileWriter = csv.writer(f, delimiter=',')
fileWriter.writerows(sortedList) # No for loop needed :)
os.remove("table.csv")
os.rename("Newtable.csv", "table.csv")
I'd suggest using pandas:
Assuming an input file like this:
team,points
team1, 5
team2, 6
team3, 2
You could do:
import pandas as pd
a = pd.read_csv('table.csv')
b=a.sort('points',ascending=False)
b.to_csv('table.csv',index=False)

Unpacking list items from a dictionary & writing to a CSV file

I have a dictionary which contains a list of 4 items per key.
I'm trying to write each individual list item to a Var column in a CSV file, but I haven't been having much luck.
try:
f = open('numbers2.csv', 'wt')
writer = csv.writer(f, lineterminator = '\n')
writer.writerow(('Var1', "Var2", 'Var3', "Var4",))
for x in exchangeDict2.iteritems():
writer.writerow(x)
This code will print the key in one column, and the list in the other.
Looks like you need to iterate over dictionary values, use itervalues():
for value in exchangeDict2.itervalues():
writer.writerow(value)
Also, use with context manager while working with files (it handles close() for you):
with open('numbers2.csv', 'wt') as f:
writer = csv.writer(f, lineterminator = '\n')
writer.writerow(('Var1', "Var2", 'Var3', "Var4",))
for value in exchangeDict2.itervalues():
writer.writerow(value)

Categories

Resources