简体   繁体   中英

I have a data of temperatures for each month of a hundred years. How do I calculate the average of the temperatures for each year?

I know this is a noob question, apologies for that. But I have a list of data in the following format:

{
    "Year": 1881,
    "Jan": -8,
    "Feb": -13,
    "Mar": 2,
    "Apr": -2,
    "May": -3,
    "Jun": -27,
    "Jul": -5,
    "Aug": -1,
    "Sep": -8,
    "Oct": -18,
    "Nov": -25,
    "Dec": -14,
    "J-D": -10,
    "D-N": -11,
    "DJF": -13,
    "MAM": -1,
    "JJA": -11,
    "SON": -17
},
{
    "Year": 1882,
    "Jan": 10,
    "Feb": 10,
    "Mar": 2,
    "Apr": -19,
    "May": -17,
    "Jun": -24,
    "Jul": -9,
    "Aug": 5,
    "Sep": 0,
    "Oct": -21,
    "Nov": -20,
    "Dec": -24,
    "J-D": -9,
    "D-N": -8,
    "DJF": 2,
    "MAM": -11,
    "JJA": -9,
    "SON": -14
},

etc.

I want to calculate the average of the temperatures for each year. There are over 100 years. What is the easiest way to do this? Putting them in arrays, and manually calculating them would take too long. Even then I don't know how to assign the average temperature to each year. What way can I write this code? I am working with Javascript.

First, you'll need an array of keys to represent the months (so you can ignore all the other data)

let months = ['Jan', 'Feb', 'Mar', ...];

Then, assuming your data is in an actual array, you can use a reduce operation (well, two reduce operations) to produce a map of year to average

 let years = [{"Year":1881,"Jan":-8,"Feb":-13,"Mar":2,"Apr":-2,"May":-3,"Jun":-27,"Jul":-5,"Aug":-1,"Sep":-8,"Oct":-18,"Nov":-25,"Dec":-14,"JD":-10,"DN":-11,"DJF":-13,"MAM":-1,"JJA":-11,"SON":-17},{"Year":1882,"Jan":10,"Feb":10,"Mar":2,"Apr":-19,"May":-17,"Jun":-24,"Jul":-9,"Aug":5,"Sep":0,"Oct":-21,"Nov":-20,"Dec":-24,"JD":-9,"DN":-8,"DJF":2,"MAM":-11,"JJA":-9,"SON":-14}]; let months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; let averages = years.reduce((avgs, year) => { let sum = months.reduce((avg, month) => avg + year[month], 0); avgs[year.Year] = sum / months.length; return avgs; }, {}); document.write('<pre>' + JSON.stringify(averages, null, ' ') + '</pre>'); 

Here's an answer using modern Array methods, which make the solution easier to read by taking the problem and breaking it down into steps.

// The data you provided
var data = [
    {
        "Year": 1881,
        "Jan": -8,
        "Feb": -13,
        "Mar": 2,
        "Apr": -2,
        "May": -3,
        "Jun": -27,
        "Jul": -5,
        "Aug": -1,
        "Sep": -8,
        "Oct": -18,
        "Nov": -25,
        "Dec": -14,
        "J-D": -10,
        "D-N": -11,
        "DJF": -13,
        "MAM": -1,
        "JJA": -11,
        "SON": -17
    },
    {
        "Year": 1882,
        "Jan": 10,
        "Feb": 10,
        "Mar": 2,
        "Apr": -19,
        "May": -17,
        "Jun": -24,
        "Jul": -9,
        "Aug": 5,
        "Sep": 0,
        "Oct": -21,
        "Nov": -20,
        "Dec": -24,
        "J-D": -9,
        "D-N": -8,
        "DJF": 2,
        "MAM": -11,
        "JJA": -9,
        "SON": -14
    },
];

// Hardcode which keys count towards the average, ignore the rest like "Year"
// and "J-D".
var months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' ');

var result = data.map(yearData => ({     // Set `result` to `data` with each
                                         // item replaced with an object with...
    Year: yearData.Year,                 // The `Year` property copied
    average: (months                     // An `average` property set to the
                                         // result of taking `months` and...
        .map(month => yearData[month])   // Replacing each item with the value
                                         // at that key in the current year data
        .reduce((a, b) => a + b)         // Then taking the sum of the Array
        / months.length                  // Then going from sum to average by
                                         // dividing by the number of items
    ),
}));

// `result` now contains the averages.

There are a lot of ways to approach the problem, this isn't the only solution. What every approach will have in common is that, one way or another, you need to iterate over the Array (done by map and reduce here), store the sum as you do (here handled implicitly by reduce ), then divide by the number of months.

Alternatively

jsFiddle

 var temps = [ { "Year": 1881, "Jan": -8, "Feb": -13, "Mar": 2, "Apr": -2, "May": -3, "Jun": -27, "Jul": -5, "Aug": -1, "Sep": -8, "Oct": -18, "Nov": -25, "Dec": -14, "JD": -10, "DN": -11, "DJF": -13, "MAM": -1, "JJA": -11, "SON": -17 }, { "Year": 1882, "Jan": 10, "Feb": 10, "Mar": 2, "Apr": -19, "May": -17, "Jun": -24, "Jul": -9, "Aug": 5, "Sep": 0, "Oct": -21, "Nov": -20, "Dec": -24, "JD": -9, "DN": -8, "DJF": 2, "MAM": -11, "JJA": -9, "SON": -14 } ], total = 0; for(var i=0, lng = temps.length; i < lng; ++i){ var y = temps[i], yearAvg = parseFloat(((y.Jan + y.Feb + y.Mar + y.Apr + y.May + y.Jun + y.Jul + y.Aug + y.Sep + y.Oct + y.Nov + y.Dec ) / 12).toFixed(2), 10); console.log(y.Year + ' average = ' + yearAvg); total += yearAvg; } document.getElementById('result').innerHTML = 'Total Avergae: ' + total/temps.length; 
 <div id="result"></div> 

I would suggest writing a python script to parse the string into a multi dimensional dictionary. The first layer of the dict should be keys representing the years and the values should hold the second layer dictionary where the keys are the months of the year and the values are the associated temperatures. From there you can write a function to iterate through the dict and calculate the averages as Jaromanda suggested.

I'd write it out for you but this is a good project to learn with. Look up python multi dimensional dictionaries and how to parse strings.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM