''' weatherstats.py Jeff Ondich, 10/12/09 This implementation of the Weather Stats program was developed with an eye towards keeping the main program easy to understand. One result of this design goal is quite a bit of redundant computation. ''' import sys import math def loadWeatherData(fileName): '''Loads temperature data from the specified file into a list of lists of integers, and returns the list. This function assumes that each line of the file consists of a year followed by some number of temperatures, all separated by commas. For example, if the file looks like this: 1939,-10,5,3,14,... 1940,2,8,-1,4,... ... 2008,7,12,3,5,-2,... (which means that on Jan 1, 1939, the high temperature was 10, etc.), then loadWeatherData will return a list of lists like this: [[1939,-10,5,3,14,...], [1940,2,...], ..., [2008,7,12,...]] ''' weatherData = [] file = open(fileName) for line in file: yearData = line.strip().split(',') yearData = map(int, yearData) weatherData.append(yearData) file.close() return weatherData def mean(listOfNumbers): '''Returns the mean of the specified list of numbers if the list contains at least one element. Otherwise, returns 0. This function assumes that its parameter refers to a (possibly empty) list of numbers.''' average = 0 if len(listOfNumbers) > 0: average = float(sum(listOfNumbers)) / float(len(listOfNumbers)) return average def standardDeviation(listOfNumbers): '''Returns the standard deviation of the specified list of numbers if the list contains 2 or more elements. Otherwise, returns 0. This function assumes that its parameter refers to a (possibly empty) list of numbers.''' if len(listOfNumbers) < 2: return 0 avg = mean(listOfNumbers) sumOfSquares = 0 for x in listOfNumbers: sumOfSquares += (x - avg)**2 return math.sqrt(sumOfSquares / float(len(listOfNumbers) - 1)) def getExtremeMeans(data): highMean = lowMean = mean(data[0][1:]) highMeanYear = lowMeanYear = data[0][0] for yearData in data: avg = mean(yearData[1:]) if avg > highMean: highMean = avg highMeanYear = yearData[0] if avg < lowMean: lowMean = avg lowMeanYear = yearData[0] return (highMean, highMeanYear, lowMean, lowMeanYear) def getExtremeStdevs(data): highStdev = lowStdev = standardDeviation(data[0][1:]) highStdevYear = lowStdevYear = data[0][0] for yearData in data: stdev = standardDeviation(yearData[1:]) if stdev > highStdev: highStdev = stdev highStdevYear = yearData[0] if stdev < lowStdev: lowStdev = stdev lowStdevYear = yearData[0] return (highStdev, highStdevYear, lowStdev, lowStdevYear) def getExtremeTemps(data): highTemp = lowTemp = data[0][1] highTempYear = lowTempYear = data[0][0] for yearData in data: for temp in yearData[1:]: if temp > highTemp: highTemp = temp highTempYear = yearData[0] if temp < lowTemp: lowTemp = temp lowTempYear = yearData[0] return (highTemp, highTempYear, lowTemp, lowTempYear) # ---- Main program starts here. ---- # # Check the command line. if len(sys.argv) != 2: sys.stderr.write('Usage: %s weatherDataFile\n' % sys.argv[0]) sys.exit(1) # Print the yearly reports. print 'High temperature data (Fahrenheit)' weatherData = loadWeatherData(sys.argv[1]) for yearData in weatherData: year = yearData[0] avg = mean(yearData[1:]) stdev = standardDeviation(yearData[1:]) print '%-8d%11.2f%11.2f' % (year, avg, stdev) print # Print the all-time reports. (highMean, highMeanYear, lowMean, lowMeanYear) = getExtremeMeans(weatherData) print 'Highest mean temperature: %.2f (%d)' % (highMean, highMeanYear) print 'Lowest mean temperature: %.2f (%d)' % (lowMean, lowMeanYear) (highStdev, highStdevYear, lowStdev, lowStdevYear) = getExtremeStdevs(weatherData) print 'Highest standard deviation: %.2f (%d)' % (highStdev, highStdevYear) print 'Lowest standard deviation: %.2f (%d)' % (lowStdev, lowStdevYear) (highTemp, highTempYear, lowTemp, lowTempYear) = getExtremeTemps(weatherData) print 'Highest temperature: %d (%d)' % (highTemp, highTempYear) print 'Lowest temperature: %d (%d)' % (lowTemp, lowTempYear)