# Count the number of riders in each category

I have a code to get riders from certain teams and calculate the number of riders in those teams in that category:

valid_clubs = []
with open("validclubs.txt") as f:
for line in f:
valid_clubs.append(line)

disqualification_reasons = ["WKG", "UPG", "ZP", "HR", "HEIGHT", "ZRVG", "new", "AGE", "DQ", "MAP", "20MINS", "5MINS"]

with open("results.csv", 'rt', encoding='UTF-8',errors='ignore') as file:  # open results file to get breakdown of results
# each variable is current number of riders in the category
A = B = C = D = E = Q = W = 0  # setting all values to 0 so we can work out number of riders in each category
try:
category = row[0]
if row[4] in valid_clubs:
if row[7] == "0":  # if club is in valid_clubs.txt and gender = female
W = W + 1  # each time this condition is met increase value of W by 1, where W is the amount of women
if "A" == category:  # if club is in valid_clubs.txt and category is A
A = A + 1  # each time this condition is met increase value of A by 1
if "B" == category:  # if club is in valid_clubs.txt and category is B
B = B + 1  # each time this condition is met increase value of B by 1
if "C" == category:  # if club is in valid_clubs.txt and category is C
C = C + 1  # each time this condition is met increase value of C by 1
if "D" == category:  # if club is in valid_clubs.txt and category is D
D = D + 1  # each time this condition is met increase value of D by 1
if category in disqualification_reasons:  # all the possible DQ reason
Q = Q + 1  # each time this condition is met increase value of Q by 1, where Q is the number of riders DQ'ed
if "E" == category:  # if club is in valid_clubs.txt and category is E
E = E + 1  # each time this condition is met increase value of E by 1
except IndexError:  # ignore errors where row is empty
pass
total = str(A + B + C + D + E + Q)
print("There were", total, "riders", W, " were women:", "\nCat A:", A, "\nCat B:", B, "\nCat C:",
C, "\nCat D:", D, "\nCat E:", E, "\nDisqualified:", Q)


It is a really repetitive code and I'm sure could be cleaned up. I would appreciate some advice on how you would do this.

Here is an example CSV:

Category.Position,Name,Time,Team,RandomInt1,RandomInt2,Male?
A,1,Person 4,00:54:12.92,2281,343,4.4,1
A,2,Person 3,00:54:13.29,10195,310,4.2,1
A,3,Person 2,00:54:19.19,84,334,5.0,1
A,4,Person 1,00:54:19.33,7535,297,4.9,1


Category would change as you go down the CSV

The Male? column is 1 when the person is male and 0 when they are female, Validclubs is a list of the team numbers which I want to use, imported from a txt file, RandomInt1/RandomInt2 are irrelevant for now

I would appreciate any advice on reducing the code so it is cleaner/shorter.

I want to use built-in libraries so not pandas.

• not pandas - why not? – Reinderien Jul 2 '20 at 19:55
• Please include your code that loads valid_clubs. – Reinderien Jul 2 '20 at 19:56
• @Reinderien I have added now, on Pandas I have never worked with them, I have no knowledge of them so if I put this in and I want to make changes to my code I would not fully understand what it is doing – PythonIsBae Jul 2 '20 at 20:00
• It's a useful thing to learn :) For small projects and datasets stock Python is fine, but you'll quickly run into performance issues when you try to scale. – Reinderien Jul 2 '20 at 20:02

## Set membership

valid_clubs = []
with open("validclubs.txt") as f:
for line in f:
valid_clubs.append(line)


should be

with open("validclubs.txt") as f:
valid_clubs = {line.strip() for line in f}


Lines coming back from a file handle in Python include their line ending, which you have to strip yourself; and you should be using a set, not a list. Set membership lookups will be much faster than list lookups.

## Consider DictReader

The csv module has a reader that gives you back a dictionary based on the headings, so that you do not have to write row[0], but rather row['Category'].

## Use Counter

Your list of category ifs can be condensed to a one-liner; read about Counter. This will be easier to use and perform better.

## Empty rows

Based on # ignore errors where row is empty, this should be done up-front. Rather than hitting your face on an IndexError and having to ignore it, simply check for an empty row:

if row: