rockdrilla

quantile.rb

Aug 3rd, 2016
415
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 3.94 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2.  
  3. ### unsorted data series
  4. Y = [
  5.     0.049632, 0.056326, 0.052863, 0.054129, 0.019590,
  6.     0.010500, 0.038988, 0.276094, 0.028402, 0.030384,
  7.     0.038914, 0.029160, 0.066111, 0.015465, 0.076519,
  8.     0.048751, 0.043617, 0.005298, 0.005722, 0.049853,
  9.     0.059949, 0.009066, 0.442716, 0.012065, 0.029591,
  10.     0.053335, 0.048495, 0.059594, 0.061983, 0.014104,
  11.     0.358289, 0.025765, 0.054330, 0.073260, 0.061888,
  12.     0.066990, 0.059203, 0.076802, 0.015893, 0.026751,
  13.     0.061616, 0.072682, 0.035666, 0.066835, 0.054902,
  14.     0.072753, 0.190644, 0.036291, 0.065030, 0.076660
  15. ]
  16.  
  17.     ### Lagrange polynomial interpolation
  18.     ### ref: https://en.wikipedia.org/wiki/Lagrange_polynomial
  19.  
  20.     ### Lagrange polynomial interpolation: helper function
  21.     def lx(f, x, i)
  22.         ret = 1.0
  23.         f.count.times { |k|
  24.             next if k == i
  25.             ret *= (x - f[k][0])
  26.         }
  27.         f.count.times { |k|
  28.             next if k == i
  29.             ret /= (f[i][0] - f[k][0])
  30.         }
  31.         return ret
  32.     end
  33.  
  34.     ### Lagrange polynomial interpolation: main function
  35.     def Lx(f, x)
  36.         ret = 0.0
  37.         f.count.times { |i|
  38.             ret += (f[i][1] * lx(f, x, i))
  39.         }
  40.         return ret
  41.     end
  42.  
  43.     def Quantile(f, a)
  44.         ### select 2 adjacent "x->y" pairs near quantile value
  45.         z = [ f.select { |xy| xy[0] <= a }.last, f.select { |xy| xy[0] > a }.first ]
  46.  
  47.     ##  return Lx(z, a)
  48.  
  49.         ### data series with 2 values doesn't need entire Lagrange polynomial
  50.         ### here is plain formula:
  51.         ###   q = (a*(y1-y0)+x1*y0+x0*y1)/(x1-x0)
  52.         ret = 0.0
  53.         ret += (z[1][0] * z[0][1] - z[0][0] * z[1][1])
  54.         ret += a * (z[1][1] - z[0][1])
  55.         ret /= (z[1][0] - z[0][0])
  56.  
  57.         return ret
  58.     end
  59.  
  60. ### in-place sort
  61. Y.sort!
  62.  
  63. ### create array of "x->y" pairs (via array with two element)
  64. ###   x = normalized index in [0;1]
  65. ###   y = sorted data series
  66. F = []
  67. Y.count.times { |z| F << [ z / (Y.count - 1.0), Y[z] ] }
  68.  
  69. ### kind of "pretty output"
  70. # F.count.times { |i|
  71. #   printf "%-10f :: %f\n", F[i][0], F[i][1]
  72. # }
  73. # puts
  74.  
  75. ### calculate several quantiles
  76. [0.05, 0.10, 0.15, 0.20, 0.25, 0.50, 0.75, 0.80, 0.85, 0.90, 0.95].each { |q|
  77.     z = Quantile(F, q)
  78.     printf "%-10f => %f (%d)\n", q, z, F.count { |xy| xy[1] < z }
  79. }
  80.  
  81. # $ ./quantile.rb
  82. # 0.000000   :: 0.005298
  83. # 0.020408   :: 0.005722
  84. # 0.040816   :: 0.009066
  85. # 0.061224   :: 0.010500
  86. # 0.081633   :: 0.012065
  87. # 0.102041   :: 0.014104
  88. # 0.122449   :: 0.015465
  89. # 0.142857   :: 0.015893
  90. # 0.163265   :: 0.019590
  91. # 0.183673   :: 0.025765
  92. # 0.204082   :: 0.026751
  93. # 0.224490   :: 0.028402
  94. # 0.244898   :: 0.029160
  95. # 0.265306   :: 0.029591
  96. # 0.285714   :: 0.030384
  97. # 0.306122   :: 0.035666
  98. # 0.326531   :: 0.036291
  99. # 0.346939   :: 0.038914
  100. # 0.367347   :: 0.038988
  101. # 0.387755   :: 0.043617
  102. # 0.408163   :: 0.048495
  103. # 0.428571   :: 0.048751
  104. # 0.448980   :: 0.049632
  105. # 0.469388   :: 0.049853
  106. # 0.489796   :: 0.052863
  107. # 0.510204   :: 0.053335
  108. # 0.530612   :: 0.054129
  109. # 0.551020   :: 0.054330
  110. # 0.571429   :: 0.054902
  111. # 0.591837   :: 0.056326
  112. # 0.612245   :: 0.059203
  113. # 0.632653   :: 0.059594
  114. # 0.653061   :: 0.059949
  115. # 0.673469   :: 0.061616
  116. # 0.693878   :: 0.061888
  117. # 0.714286   :: 0.061983
  118. # 0.734694   :: 0.065030
  119. # 0.755102   :: 0.066111
  120. # 0.775510   :: 0.066835
  121. # 0.795918   :: 0.066990
  122. # 0.816327   :: 0.072682
  123. # 0.836735   :: 0.072753
  124. # 0.857143   :: 0.073260
  125. # 0.877551   :: 0.076519
  126. # 0.897959   :: 0.076660
  127. # 0.918367   :: 0.076802
  128. # 0.938776   :: 0.190644
  129. # 0.959184   :: 0.276094
  130. # 0.979592   :: 0.358289
  131. # 1.000000   :: 0.442716
  132. #
  133. # 0.050000   => 0.009711 (3)
  134. # 0.100000   => 0.013900 (5)
  135. # 0.150000   => 0.017187 (8)
  136. # 0.200000   => 0.026554 (10)
  137. # 0.250000   => 0.029268 (13)
  138. # 0.500000   => 0.053099 (25)
  139. # 0.750000   => 0.065841 (37)
  140. # 0.800000   => 0.068128 (40)
  141. # 0.850000   => 0.073083 (42)
  142. # 0.900000   => 0.076674 (45)
  143. # 0.950000   => 0.237642 (47)
Add Comment
Please, Sign In to add comment