RonTheBear
RonTheBear

Reputation: 91

Column in CSV to list in python?

I've seen a lot of posts about doing this backwards, but I haven't been able to find any way to write the contents of a column in a csv file to a list. After I have this I'll loop through to add all of the unique value to a separate list and count the number of total unique values. This is what I have:

b=[]
c=[]
servers = []
fname=(r'file')
with open(fname, 'r') as f:
    reader = csv.reader(f)
    severities = Counter(row[3] for row in reader)
    servers = list(row[9] for row in reader)
    for row in reader:
        print (row[9])
        for servername in servers:
            if servername not in b:
                b.append(servername)

I'm open to better ways to do this. Any and all help is appreciated. Thanks in advance.

Upvotes: 1

Views: 146

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1124848

Your best bet is to loop over reader just once and collect the counts and unique names for the servers in your loop:

severities = Counter()
servers = set()

with open(fname, 'rb') as f:
    reader = csv.reader(f)
    for row in reader:
        severities[row[3]] += 1
        servers.add(row[9])

This assumes you don't care about the order servers are listed in in the CSV file.

If order does need to be preserved, use a separate seen set:

severities = Counter()
servers = []

with open(fname, 'rb') as f:
    reader = csv.reader(f)
    seen = set()
    for row in reader:
        severities[row[3]] += 1
        if row[9] not in seen:
            servers.append(row[9])
            seen.add(row[9])

If the file is relatively small, you could also get away with transposing the columns; that's overkill here, but would look like:

with open(fname, 'rb') as f:
    reader = csv.reader(f)
    cols = zip(*reader)  # transpose the rows to columns
    severities = Counter(cols[3])
    servers = set(cols[9])

Upvotes: 0

Andrea Corbellini
Andrea Corbellini

Reputation: 17781

You are iterating over the reader three times:

severities = Counter(row[3] for row in reader)  # First time
servers = list(row[9] for row in reader)  # Second time
for row in reader:  # Third time

When you iterate the first time, you 'exhaust' it, so it won't yield any item the second and third time.

You should do something like this:

severities = Counter()
servers = []
for row in reader:
    severities[row[3]] += 1
    servers.append(row[9])
    print row[9]

This is enough to make the code work.

Here are some other tips. They aren't required to fix your code, however you'll surely benefit from them:

  • I think you want to place the for servername in servers loop out of the for row in reader loop.
  • If you use a set or an OrderedSet instead of a list for b, you can completely avoid the for servername in servers loop and replace it with a single line:

    b.update(servers)
    

Upvotes: 2

Related Questions