Skip to content

Commit 0ce825b

Browse files
Merge pull request #34 from juliangehring/general-step-functions
Bring adjustment stepup and stepdown together
2 parents 96fd750 + d38046a commit 0ce825b

File tree

2 files changed

+39
-26
lines changed

2 files changed

+39
-26
lines changed

src/pval-adjustment.jl

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ function benjamini_hochberg(pValues::PValues, n::Integer)
4040
end
4141
sortedIndexes, originalOrder = reorder(pValues)
4242
sortedPValues = pValues[sortedIndexes]
43-
stepup!(sortedPValues, bejamini_hochberg_multiplier, k, n)
43+
stepup!(sortedPValues, bejamini_hochberg_step, k, n)
4444
return min(sortedPValues[originalOrder], 1)
4545
end
4646

47-
bejamini_hochberg_multiplier(i::Int, k::Int, n::Int) = n/(k-i)
47+
bejamini_hochberg_step(p::AbstractFloat, i::Int, k::Int, n::Int) = p * n/(k-i)
4848

4949

5050
# Benjamini-Hochberg Adaptive
@@ -83,11 +83,11 @@ function benjamini_yekutieli(pValues::PValues, n::Integer)
8383
end
8484
sortedIndexes, originalOrder = reorder(pValues)
8585
sortedPValues = pValues[sortedIndexes]
86-
stepup!(sortedPValues, benjamini_yekutieli_multiplier, k, n)
86+
stepup!(sortedPValues, benjamini_yekutieli_step, k, n)
8787
return min(sortedPValues[originalOrder], 1)
8888
end
8989

90-
benjamini_yekutieli_multiplier(i::Int, k::Int, n::Int) = sum(1./(1:n))*n/(k-i)
90+
benjamini_yekutieli_step(p::AbstractFloat, i::Int, k::Int, n::Int) = p * harmonic_number(n) * n/(k-i)
9191

9292

9393
# Benjamini-Liu
@@ -107,11 +107,11 @@ function benjamini_liu(pValues::PValues, n::Integer)
107107
end
108108
sortedIndexes, originalOrder = reorder(pValues)
109109
sortedPValues = pValues[sortedIndexes]
110-
general_stepdown!(sortedPValues, benjamini_liu_step, k, n)
110+
stepdown!(sortedPValues, benjamini_liu_step, k, n)
111111
return min(sortedPValues[originalOrder], 1)
112112
end
113113

114-
function benjamini_liu_step(p::AbstractFloat, i::Int, n::Int)
114+
function benjamini_liu_step(p::AbstractFloat, i::Int, k::Int, n::Int)
115115
# a bit more involved because cutoffs at significance α have the form:
116116
# P_(i) <= 1- [1 - min(1, m/(m-i+1)α)]^{1/(m-i+1)}
117117
s = n-i+1
@@ -136,11 +136,11 @@ function hochberg(pValues::PValues, n::Integer)
136136
end
137137
sortedIndexes, originalOrder = reorder(pValues)
138138
sortedPValues = pValues[sortedIndexes]
139-
stepup!(sortedPValues, hochberg_multiplier, k, n)
139+
stepup!(sortedPValues, hochberg_step, k, n)
140140
return min(sortedPValues[originalOrder], 1)
141141
end
142142

143-
hochberg_multiplier(i::Int, k::Int, n::Int) = n-k+i+1
143+
hochberg_step(p::AbstractFloat, i::Int, k::Int, n::Int) = p * (n-k+i+1)
144144

145145

146146
# Holm
@@ -160,11 +160,11 @@ function holm(pValues::PValues, n::Integer)
160160
end
161161
sortedIndexes, originalOrder = reorder(pValues)
162162
sortedPValues = pValues[sortedIndexes]
163-
stepdown!(sortedPValues, holm_multiplier, k, n)
163+
stepdown!(sortedPValues, holm_step, k, n)
164164
return min(sortedPValues[originalOrder], 1)
165165
end
166166

167-
holm_multiplier(i::Int, n::Int) = n-i+1
167+
holm_step(p::AbstractFloat, i::Int, k::Int, n::Int) = p * (n-i+1)
168168

169169

170170
# Hommel
@@ -227,37 +227,29 @@ function forwardstop(pvalues::PValues, n::Integer)
227227
k = length(pvalues)
228228
check_number_tests(k, n)
229229
logsums = -cumsum(log(1-pvalues))
230-
stepup!(logsums, forwardstop_multiplier, k, n)
230+
stepup!(logsums, forwardstop_step, k, n)
231231
return max(min(logsums, 1), 0)
232232
end
233233

234-
forwardstop_multiplier(i::Int, k::Int, n::Int) = 1/(k-i)
234+
forwardstop_step(p::AbstractFloat, i::Int, k::Int, n::Int) = p * 1/(k-i)
235235

236236

237237
## internal ##
238238

239239
# step-up / step-down
240240

241-
function stepup!{T<:AbstractFloat}(sortedPValues::AbstractVector{T}, multiplier::Function, k::Integer, n::Integer)
242-
sortedPValues[k] *= multiplier(0, k, n)
241+
function stepup!{T<:AbstractFloat}(sortedPValues::AbstractVector{T}, stepfun::Function, k::Integer, n::Integer)
242+
sortedPValues[k] = stepfun(sortedPValues[k], 0, k, n)
243243
for i in 1:(k-1)
244-
sortedPValues[k-i] = min(sortedPValues[k-i+1], sortedPValues[k-i] * multiplier(i, k, n))
244+
sortedPValues[k-i] = min(sortedPValues[k-i+1], stepfun(sortedPValues[k-i], i, k, n))
245245
end
246246
return sortedPValues
247247
end
248248

249-
250-
function stepdown!{T<:AbstractFloat}(sortedPValues::AbstractVector{T}, multiplier::Function, k::Integer, n::Integer)
251-
stepfun(p::AbstractFloat, i::Int, n::Int) = p * multiplier(i, n)
252-
general_stepdown!(sortedPValues, stepfun, k, n)
253-
return sortedPValues
254-
end
255-
256-
257-
function general_stepdown!{T<:AbstractFloat}(sortedPValues::AbstractVector{T}, stepfun::Function, k::Integer, n::Integer)
258-
sortedPValues[1] = stepfun(sortedPValues[1], 1, n)
249+
function stepdown!{T<:AbstractFloat}(sortedPValues::AbstractVector{T}, stepfun::Function, k::Integer, n::Integer)
250+
sortedPValues[1] = stepfun(sortedPValues[1], 1, k, n)
259251
for i in 2:k
260-
sortedPValues[i] = max(sortedPValues[i-1], stepfun(sortedPValues[i], i, n))
252+
sortedPValues[i] = max(sortedPValues[i-1], stepfun(sortedPValues[i], i, k, n))
261253
end
262254
return sortedPValues
263255
end
@@ -269,3 +261,6 @@ function check_number_tests(k::Integer, n::Integer)
269261
throw(ArgumentError(msg))
270262
end
271263
end
264+
265+
266+
harmonic_number(n::Integer) = digamma(n+1) + γ

test/test-utils.jl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@ using Base.Test
103103
end
104104

105105

106+
@testset "harmonic_number" begin
107+
108+
# Exact computation as reference
109+
harm_n_exact(n::Integer) = sum([Rational(1, i) for i in 1:BigInt(n)])
110+
111+
n = [1:100; 200:200:1000; 10000]
112+
113+
max_d = 0.0
114+
for i in n
115+
hn1 = MultipleTesting.harmonic_number(i)
116+
hn2 = harm_n_exact(i)
117+
max_d = max(abs(hn1 - hn2), max_d)
118+
end
119+
# approximation error in the range of floating point inaccuracy
120+
@test max_d < (10*eps())
121+
122+
end
123+
106124
end
107125

108126
end

0 commit comments

Comments
 (0)