Skip to content

utility_weather_sensitivity

David M. Lorenzetti edited this page Oct 6, 2014 · 1 revision

Weather sensitivity metric

Introduction

Weather sensitivity refers to the strength of the correlation between building load and outside air temperature. The weather sensitivity metric described here uses the Spearman rank correlation coefficient:

  • A value of +1 indicates that the load increases as a monotone function of outside air temperature.
  • A value of 0 indicates no rank-order correlation between load and outdoor temperature.
  • A value of -1 is unexpected value, as it indicates that load continously decreases with temperature.

Note this is not a stand-alone application. Rather, it is calculated for display along with the energy signature plot.

Pseudo-code: Weather sensitivity

Find the Spearman coefficient by finding the correlation between the ranks of the loads and temperatures.

Sample explanatory text: "If weather sensitivity > 0.7 the building energy use is "highly" sensitive to outside air temperature. There may be opportunities to improve building insulation and ventilation."

Program findSpearmanRank

  • Get inputs:
    • xValues and yValues, two vectors of values (float). For weather sensitivity, xValues are the outside air temperatures, and yValues are the corresponding loads. However, note that interchanging xValues and yValues will still give the same correlation coefficient.
  • Assume:
    • Both xValues and yValues have the same number of entries.
    • Any missing or corrupted entries in xValues and yValues have been marked as NAN (not-a-number). These entries will be excluded from the analysis.
  • Identify the data of interest:
    • Take the last year of data. This ensures that the data are representative.
  • Remove invalid pairs of entries:
    • Set xValuesClean to an empty list.
    • Set yValuesClean to an empty list.
    • For each matched pair x, y taken from xValues and yValues:
      • If either x or y is a NAN, discard the pair.
      • Otherwise, append x to xValuesClean, and append y to yValuesClean.
    • Here, both xValuesClean and yValuesClean should have the same number of entries, call it valCt.
  • Rank the remaining entries:
    • Set xRanks = rankForSpearman(xValuesClean).
    • Set yRanks = rankForSpearman(yValuesClean).
    • Note the pseudo-code for subprogram rankForSpearman() appears below.
    • Note both xRanks and yRanks are vectors containing valCt ranks. For any valid index ii, the entry xRanks[ii] gives the ranking that xValuesClean[ii] would have if sorted into ascending order. However, duplicate entries are assigned the mean rank of all the duplicates. Therefore the entries are not necessarily integers.
  • Subtract out the mean ranks:
    • Set xRanksZeroMean to xRanks minus the mean of all entries in xRanks.
    • Set yRanksZeroMean to yRanks minus the mean of all entries in yRanks.
  • Find the Spearman rank correlation coefficient:
    • Set cosineFactor to the inner (dot) product of xRanksZeroMean with yRanksZeroMean.
    • Set xMagSq to the inner (dot) product of xRanksZeroMean with itself.
    • Set yMagSq to the inner (dot) product of yRanksZeroMean with itself.
    • Find the Spearman coefficient using: spearmanCoeff = cosineFactor / sqrt(xRanks * yMagSq)
    • Note that the Spearman coefficient is the Pearson coefficient of the rank vectors xRanks and yRanks.
    • Note that expect -1 <= spearmanCoeff <= 1.
  • Return spearmanCoeff.

Subprogram rankForSpearman ranks the entries of a vector values, using the average rank to break ties:

Subprogram rankForSpearman

  • Get inputs:
    • values, vector containing valCt numbers (float).
  • Assume:
    • All entries in values are numeric, i.e., the vector does not contain any NAN entries.
  • Find the sorted order of entries in values:
    • Set srtdToActIdx to a vector of valCt indices that would sort values, from smallest to largest. That is, srtdToActIdx[ii] should give the index of the iith entry in a sorted version of values.
    • Duplicate entries in values may be sorted in any order. That is, it is not necessary to perform a "stable sort" that preserves the original order of duplicate entries in values.
    • For example, if values = (6.6, 1.1, 3.3, 1.1) then srtdToActIdx = (1, 3, 2, 0) is a possible ranking. Consider ii = 3. Since srtdToActIdx[3] = 0, it follows that values[0] = 6.6 would be at index 3 in a sorted version of values. Note that there is one other possible ranking, due to the duplicated entry 1.1 in values. Also note that, in programming languages that index arrays from 1 (such as R or Fortran), the entries in srtdToActIdx should be one greater than shown in the example.
    • Note that merely sorting values is not helpful, because the simple act of sorting does not retain information about which index of the original values vector provided each entry in the sorted vector.
    • In practice, some high-level programming environments provide sorting routines that return the indices needed to sort a vector. This is exactly the required srtdToActIdx.
  • Find the average rank order of each entry in values:
    • Initialize ranks as a vector of valCt entries, all equal to 0.
    • Set lastVal to values[srtdToActIdx[0]]. Note this should be the smallest entry in values.
    • Set startRunIdx to 0.
    • For currIdx running from 1 to valCt-1 (i.e., for every entry after the first):
      • Set currVal to the corresponding entry in the sorted vector, i.e., to values[srtdToActIdx[currIdx]].
      • If( currVal is different from lastVal ):
        • Find the mean rank that should be assigned to indices startRunIdx through currIdx-1, inclusive. The sorted rank at currIdx-1 is currIdx, so find the mean rank as meanRank = 0.5 * (startRunIdx + currIdx + 1)
        • Note that in a language that indexes arrays from 1, the sorted rank at currIdx-1 is currIdx-1, so the mean rank is meanRank = 0.5 * (startRunIdx + currIdx - 1)
        • while( startRunIdx < currIdx ):
          • Set ranks[srtdToActIdx[startRunIdx]] to meanRank.
          • Increment startRunIdx by 1.
        • Set lastVal to currVal, in order to mark the start of a new run of equal values. Note that startRunIdx should already be equal to currIdx, due to the while-loop above.
    • Assign ranks to the last entries inspected in the loop above:
      • Set meanRank to the mean rank, using the same formula shown above.
      • while( startRunIdx < currIdx ):
        • Set ranks[srtdToActIdx[startRunIdx]] to meanRank.
        • Increment startRunIdx by 1.
    • Here, every entry of ranks should have the rank of the corresponding entry in values, with equal values assigned their mean rank, and with NAN values assigned a rank of 0. Continuing the example above, if values = (6.6, 1.1, 3.3, 1.1) then ranks = (4, 1.5, 3, 1.5) Note that, unlike the entries in srtdToActIdx, ranks does not depend on whether the programming language indexes arrays from 0 or from 1. Ranks always range from 1 (or larger, for the smallest non-NAN entry in values) to valCt (or less, for the largest non-NAN entry in values).
  • Return ranks.