Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Viola Tian
Viola Tian
386 Points

Weather Statistics HELP???

You have no need to change much of the main function or any of the supplied complete functions.

Function headers for the ones you must write are supplied, as are their doc strings.

def readData(filename): '''Reads the weather data from the supplied filename. The function returns a list of dictionaries, where each dictionary consists of the data for a particular month.''' # You can see the key names used by examining the code given below. fileIn = open(filename, 'r') allData = [] line = fileIn.readline() while line != "": line = fileIn.readline().strip() if line != "": values = line.split(',') monthData = {} monthData['year'] = int(values[0]) monthData['month'] = int(values[1]) monthData['meanT'] = float(values[2]) monthData['maxT'] = float(values[3]) monthData['minT'] = float(values[4]) monthData['rain'] = float(values[5]) monthData['snow'] = float(values[6]) allData.append(monthData) fileIn.close() return allData

def showSome(allData): '''A convenience function that prints the beginning and end portions of the supplied list.''' for i in range(10): print(allData[i]) print("<snip>") for i in range(-10, 0): print(allData[i])

def getInt(prompt, lowLimit=None, highLimit=None): '''A robust function that is sure to return an int value between the two supplied limits.''' numberOK = False while not numberOK: try: userNum = int(input(prompt)) if lowLimit != None and userNum < lowLimit: print("The number must be higher than", lowLimit) print("Please try again.") elif highLimit != None and userNum > highLimit: print("The number must be lower than", highLimit) print("Please try again.") else: numberOK = True except ValueError: print("Your entry is not a valid integer, please try again.") return userNum

def addYearMonthKey(allData): '''Calculates and adds a key:value pair to each dictionary in the supplied list. The key will be named 'yearmonth' and will have a value of (100 * year + month).''' for monthData in allData: monthData['yearmonth'] = monthData['year'] * 100 + monthData['month']

def insertionSort(allData, key): '''Sorts the supplied list of dictionaries in situ into increasing order by the key name supplied.''' # You don't have to use insertion sort, but you should not use bubble sort and # cannot use any of the built-in Python sorts. Remove the "pass" line and add your # own code: pass

def findRain(allData, target): '''Uses a binary search to locate rainfall amounts in mm from the supplied list of dictionaries. target is a date in the 'yearmonth' value format. The function assumes that the list has been sorted by increasing date. The function will raise a ValueError exception if the year and month in target do not exist in allData.''' # You must use a binary seach and cannot use any built-in searches. pass

def findMax(allData, key): '''Returns the record from allData that has the maximum value for the supplied key.''' # You cannot use any built-in searches including the max() BIF. pass

def findMin(allData, key): '''Returns the record from allData that has the minimum value for the supplied key.''' # You cannot use any built-in searches including the min() BIF. pass

def getAnnualSnow(allData): '''This function returns a list of dictionaries which consist of the total snowfall for every year listed in allData. Each record will consist of {'year' : ####, 'totalsnow' : ###.#}, where # is a number. There will be one record per year. It does not matter if any month records are missing, the total snowfall is still calculated, by assuminng zero snow for the missing months.''' pass

def saveAnnualMeanTemp(allData, filename): '''This function calculates the mean temperatures for an entire year and saves this data to the supplied file - one line in the file per year. It is assumed that each year from 1938 to 2012 has 12 months.''' pass

def main(): # Read the data db = readData("TorontoWeatherData.csv") # Un-comment these lines to make sure your sort has worked properly. #print("Before sorting, as read from file:") #showSome(db) addYearMonthKey(db) insertionSort(db, 'yearmonth') #print("\nAfter sorting by date:") #showSome(db)

# Test your binary search by searching for the rainfall amount for a user-
# supplied year and month.
searchYear = getInt("Enter year for rainfall search: ", 1938, 2012)
searchMonth = getInt("Enter month for rainfall search: ", 1, 12)
searchYearMonth = 100 * searchYear + searchMonth
try:
    rainfall = findRain(db, searchYearMonth)
    print("Rainfall was {0} mm.".format(rainfall))
except ValueError as message:
    print(message)

# Test your findMax and findMin functions by locating some extremes.
# These two functions return a single record which is a dictionary.
maxR = findMax(db, 'maxT')
print("\nHighest temperature {0} deg C, in month {1}, {2}.".format(maxR['maxT'], maxR['month'], maxR['year']))
minR = findMin(db, 'minT')
print("Lowest temperature {0} deg C, in month {1}, {2}.".format(minR['minT'], minR['month'], minR['year']))
maxR = findMax(db, 'rain')
print("Highest rainfall {0} mm, in month {1}, {2}.".format(maxR['rain'], maxR['month'], maxR['year']))
maxR = findMax(db, 'snow')
print("Highest snowfall {0} cm, in month {1}, {2}.".format(maxR['snow'], maxR['month'], maxR['year']))

# annualSnow is a list of dictionaries, where each dictionary holds the year and the total snowfall
# for that year.
annualSnow = getAnnualSnow(db)
insertionSort(annualSnow, 'totalsnow')
minR = annualSnow[0]
print("\nLowest annual snowfall {0} cm, in {1}.".format(minR['totalsnow'], minR['year']))
medR = annualSnow[len(annualSnow) // 2]
print("Median annual snowfall {0} cm.".format(medR['totalsnow']))    
maxR = annualSnow[len(annualSnow) - 1]
print("Highest annual snowfall {0} cm, in {1}.".format(maxR['totalsnow'], maxR['year']))

# Sort your data again, by mean temperature this time.  This is the only way you can get the median
# value, which is defined as the middle of a sorted set of values.
insertionSort(db, 'meanT')
minR = db[0]
print("\nLowest mean temperature {0} deg C, in month {1}, {2}.".format(minR['meanT'], minR['month'], minR['year']))
medR = db[len(db) // 2]
print("Median mean temperature {0} deg C.".format(medR['meanT']))
maxR = db[-1]
print("Highest mean temperature {0} deg C, in month {1}, {2}.".format(maxR['meanT'], maxR['month'], maxR['year']))

# Look for Global Warming!
saveAnnualMeanTemp(db, "YearMeans.txt")

main()

Basically, you will need to carry out various search and sorts on actual historical weather data.

Here is some actual historical weather data for the city of Toronto (at Pearson Airport): TorontoWeatherData.csv from January 1938 to December 2012, downloaded from Environment Canada's National Climate Data and Information Archive. Unfortuntately they no longer seem to be keeping this archive up-to-date and it does not contain data for 2013 or 2014. It consists of 7 columns of numeric data:

The year. The month in that year as a number between 1 and 12 inclusive. The mean temperature for that month. The maximum temperature for that month. The minimum temperature for that month. The total rainfall for that month in mm. The total snowfall for that month in cm.

You will see that the data is all mixed up! The data will be contained in a list of dictionaries with a key in each dictionary for each of the 7 pieces of data, and one dictionary per month. You will need to carry out various searches and sorts on this data, starting by sorting it by date. Your sort function will be provided with the list of dictionaries (passed by reference) and the name of the key to sort by, as a string. As you will see when sorting by date it is easiest to use the key "yearmonth", which must include the year and month. The easiest way to do this is to add a new key:value pair to each dictionary of data, which will be a combination of year and month: 100 * year + month, using the key name "yearmonth".

Stephen Cole
Stephen Cole
Courses Plus Student 15,809 Points

I'm not sure what the the question is here.

Where are you stuck?