Project 5

Download the file vabirds.csv.

  1. Create a struct birdData in files birdData.h and birdData.cxx.
  2. Write the following functions, implemented in birdDat.cxx.
  • Write a stats procedure that takes only an instance of the struct and returns the mean and standard deviation of the observations for that instance. Hint: one way to return multiple items in C++ is to use a vector.
  • Write a minmax procedure that takes an instance of the type and the array of years and returns the maximum observed, the minimum observed, and the years for maximum and minimum. You may use the maxval, minval, maxloc, and minloc intrinsics.
  • Write a main program that uses your struct. Look up the sort

Write a read_data routine that uses the number of items in the file, corrected for the header and the two footers, to allocate a vector of bird_data types.
Loop through this vector to load the data for each species.
The read_data routine should return the vector of years and the vector of bird_data types.

Request a species name from the user. Find the species in your vector of types and print its mean, standard deviation, and results from minmax. Print some appropriate message if the species is not found. Compute a vector of the means for all species.
Use the built-in sort to sort the means vector. However, we also want the permutation vector, which is a vector of the indices of the original positions.
For example, if after the sort the permutation vector is (17,3,55,11,23, and so forth) that means that the element that was previously 17 is now the first in the new array, and so on.
Using online resources, figure out how to do this. Hint: you will need to use a “custom comparitor.”

Test the user input portion for
TurkeyVulture
TuftedTitmouse
ElegantTrogon

For this project you can require an exact match of the species name. (Note that no spaces are allowed and words are separated by capitalization; we would have to do more sophisticated string handling if we were to allow spaces and variations in capitalization.)

Sample solution

/*
 * 
 * **********************************************************
 * 
 * Author: K. Holcomb
 *
 * Class describing some data about bird observations.
 * 
 * Changelog: Modified from old student homework 20170410
 * 
 * 
 * **********************************************************
 * 
 */

#include <cmath>
#include <string>
#include <vector>

using namespace std;

typedef struct {
	
//Input values.
    string commonName;
    vector<float> observations;
} birdData;

vector<float> stats(birdData); 
vector<float> minmax(birdData, vector<int>); 

/*
 * 
 * **********************************************************
 * 
 * Author: K. Holcomb
 *
 * 
 * Changelog: Modified from old student homework 20170410
 * 
 * **********************************************************
 * 
 */

#include <cmath>
#include <string>
#include <vector>
#include <iostream>
#include "birdData.h"

using namespace std;

vector<float> stats(birdData bird) {
    float sum=0,devSum=0;
    int yearsObs=bird.observations.size();
    for (int i=0;i<yearsObs;i++) {
        sum+=bird.observations[i];
    }

    float mean=sum/yearsObs;
    for (int i=0;i<yearsObs;i++) {
         devSum+=pow((mean-bird.observations[i]),2);
   }

   float stdev=sqrt(devSum/yearsObs);
   vector<float> birdStats={mean,stdev};
   return birdStats;
}

vector<float> minmax(birdData bird,vector <int> years) {
    int minIndex=0, maxIndex=0;
    float minimum=bird.observations[0];
    float maximum=bird.observations[0];
    int yearsObs=years.size();
    for (int i=1;i<yearsObs;i++) {
    //If multiple occurrences, will return last one.
        if (bird.observations[i]<=minimum) {
            minimum=bird.observations[i];
            minIndex=i;
        }
        if (bird.observations[i]>=maximum) {
            maximum=bird.observations[i];
            maxIndex=i;
        }
    }

    vector<float> minmaxes={minimum,maximum,(float) years[minIndex],(float) years[maxIndex]};
    return minmaxes;
}

/*
 * 
 * **********************************************************
 * 
 * Author: K. Holcomb
 * 
 * Changelog: Modified from old student homework 20170410
 * 
 * 
 * **********************************************************
 * 
 */

#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include "birdData.h"

using namespace std;

int main(int argc, char *argv[])
{		
    ifstream inFile;
    string species;
    vector<birdData> birds;
    vector<int> years;
		
    float obs;
    inFile.open(argv[1]);
    if (inFile.is_open()) {		
	string line,header,yearString;
        int year;
	getline(inFile,line);
	stringstream yearStream(line);
	while (getline(yearStream,yearString,',')) {
                stringstream ssyear;
                ssyear<<yearString;
                if (ssyear>>year) {
		    years.push_back(year);
                }
	}
	//Dummy for storing species strings before writing to vector.
	string speciesDatum;
	while ( getline(inFile,line) ){
            stringstream lineStream(line);
            vector<string> obsVals;
            while (getline(lineStream,speciesDatum,',')) {
                obsVals.push_back(speciesDatum);
            }
            //Create a vector of bird instances.
           birdData bird;
	   bird.commonName=obsVals.at(0);
           for (int index=1;index<obsVals.size();++index){
	       stringstream obsString;
               obsString<<obsVals[index];
               obsString>>obs;
               bird.observations.push_back(obs);
           }
           
           birds.push_back(bird);
        }
    }
    else {
        cout<<"Unable to open data file\n";
        return 1;
    }

    int numLines=birds.size();
    //Clip off last two lines
    birds.erase(birds.end()-1,birds.end());
    int numSpecies=numLines-2;


    string userInput;
    cout<<"Please enter the name of a bird species: ";
    cin>>userInput;
    int speciesIndex=-1;
    for (int i=0;i<numSpecies;i++) {
	if (birds[i].commonName==userInput) {
            speciesIndex=i;
            break;
	}
    }
    if (speciesIndex==-1) {
	cout<<endl<<"No such species. Please start over."<<endl<<endl;
    }
    else {		
        float minVal, maxVal;
        int   minYear, maxYear;
	cout<<endl<<"The "<<userInput<<" species was observed an average of ";
        vector<float> birdStats=stats(birds[speciesIndex]);
        float mean=birdStats[0]; float stdev=birdStats[1];
        cout<<mean<<" times, ";
	cout<<"with a"<<endl<<"standard deviation of "<<stdev;
        vector<float> yearObs=minmax(birds[speciesIndex],years);
        minVal=yearObs[0]; maxVal=yearObs[1];
        minYear=(int) yearObs[2]; maxYear=(int) yearObs[3];
	cout<<" a maximum of "<<maxVal<<" in year "<<maxYear;;
	cout<<", and a minimum of "<<minVal<<" in year "<<minYear<<".\n";
    }

    vector<float> means(numSpecies);
    for (int i=0;i<numSpecies;i++) {
	means[i]=stats(birds[i])[0];
    }
    int mostCommon=10;
    int tenCommonIndex=numSpecies-mostCommon;				

    vector<int> index(numSpecies);
    for (int i=0;i<numSpecies;++i) {
        index[i]=i;
    }

    sort(index.begin(), index.end(), [&](const int& a, const int& b) {
        return (means[a] < means[b]); });
			
    cout<<"The 10 most common species (in order of decreasing ";
    cout<<"prevalence) are:"<<endl;
    int j;
    for (int i=0;i<mostCommon;i++) {
        j=numSpecies-i-1;
        cout<<birds[index[j]].commonName<<"    \t"<<means[index[j]]<<endl;
    }
    cout<<endl<<endl;

    return 0;

}

Previous
Next