1
1
package org.jetbrains.kotlinx.dataframe.math
2
2
3
- import org.jetbrains.kotlinx.dataframe.api.isNaN
4
3
import org.jetbrains.kotlinx.dataframe.api.skipNA_default
5
4
import org.jetbrains.kotlinx.dataframe.impl.api.toBigDecimal
6
5
import org.jetbrains.kotlinx.dataframe.impl.convertToUnifiedNumberType
@@ -13,52 +12,53 @@ import kotlin.reflect.KType
13
12
import kotlin.reflect.full.withNullability
14
13
import kotlin.reflect.typeOf
15
14
16
- /* * @include [Sequence.mean ] */
15
+ /* * @include [Sequence.meanOrNull ] */
17
16
@PublishedApi
18
- internal fun <T : Number > Iterable<T>.mean (type : KType , skipNA : Boolean = skipNA_default): Number ? =
19
- asSequence().mean (type, skipNA)
17
+ internal fun <T : Number > Iterable<T>.meanOrNull (type : KType , skipNA : Boolean = skipNA_default): Number ? =
18
+ asSequence().meanOrNull (type, skipNA)
20
19
21
20
/* *
22
21
* Returns the mean of the numbers in [this].
23
22
*
24
23
* If the input is empty, the return value will be `null`.
25
24
*
26
25
* If the [type] given or input consists of only [Int], [Short], [Byte], [Long], [Double], or [Float],
27
- * the return type will be [Double]`?` (Never `NaN`) .
26
+ * the return type will be [Double].
28
27
*
29
- * If the [type] given or the input contains [BigInteger] or [BigDecimal], the return type will be [BigDecimal]`?`.
28
+ * If the [type] given or the input contains [BigInteger] or [BigDecimal],
29
+ * the return type will be [BigDecimal].
30
30
* @param type The type of the numbers in the sequence.
31
31
* @param skipNA Whether to skip `NaN` values (default: `false`). Only relevant for [Double] and [Float].
32
32
*/
33
33
@Suppress(" UNCHECKED_CAST" )
34
- internal fun <T : Number > Sequence<T>.mean (type : KType , skipNA : Boolean = skipNA_default): Number ? {
34
+ internal fun <T : Number > Sequence<T>.meanOrNull (type : KType , skipNA : Boolean = skipNA_default): Number ? {
35
35
if (type.isMarkedNullable) {
36
- return filterNotNull().mean (type.withNullability(false ), skipNA)
36
+ return filterNotNull().meanOrNull (type.withNullability(false ), skipNA)
37
37
}
38
38
return when (type.classifier) {
39
- // Double -> Double?
40
- Double ::class -> (this as Sequence <Double >).mean (skipNA). takeUnless { it.isNaN }
39
+ // Double -> Double
40
+ Double ::class -> (this as Sequence <Double >).meanOrNull (skipNA)
41
41
42
- // Float -> Double?
43
- Float ::class -> (this as Sequence <Float >).mean (skipNA). takeUnless { it.isNaN }
42
+ // Float -> Double
43
+ Float ::class -> (this as Sequence <Float >).meanOrNull (skipNA)
44
44
45
- // Int -> Double?
46
- Int ::class -> (this as Sequence <Int >).map { it.toDouble() }.mean (false ). takeUnless { it.isNaN }
45
+ // Int -> Double
46
+ Int ::class -> (this as Sequence <Int >).map { it.toDouble() }.meanOrNull (false )
47
47
48
- // Short -> Double?
49
- Short ::class -> (this as Sequence <Short >).map { it.toDouble() }.mean (false ). takeUnless { it.isNaN }
48
+ // Short -> Double
49
+ Short ::class -> (this as Sequence <Short >).map { it.toDouble() }.meanOrNull (false )
50
50
51
- // Byte -> Double?
52
- Byte ::class -> (this as Sequence <Byte >).map { it.toDouble() }.mean (false ). takeUnless { it.isNaN }
51
+ // Byte -> Double
52
+ Byte ::class -> (this as Sequence <Byte >).map { it.toDouble() }.meanOrNull (false )
53
53
54
- // Long -> Double?
55
- Long ::class -> (this as Sequence <Long >).map { it.toDouble() }.mean (false ). takeUnless { it.isNaN }
54
+ // Long -> Double
55
+ Long ::class -> (this as Sequence <Long >).map { it.toDouble() }.meanOrNull (false )
56
56
57
- // BigInteger -> BigDecimal?
58
- BigInteger ::class -> (this as Sequence <BigInteger >).mean ()
57
+ // BigInteger -> BigDecimal
58
+ BigInteger ::class -> (this as Sequence <BigInteger >).meanOrNull ()
59
59
60
- // BigDecimal -> BigDecimal?
61
- BigDecimal ::class -> (this as Sequence <BigDecimal >).mean ()
60
+ // BigDecimal -> BigDecimal
61
+ BigDecimal ::class -> (this as Sequence <BigDecimal >).meanOrNull ()
62
62
63
63
// Number -> Conversion(Common number type) -> Number? (Double or BigDecimal?)
64
64
// fallback case, heavy as it needs to collect all types at runtime
@@ -69,7 +69,7 @@ internal fun <T : Number> Sequence<T>.mean(type: KType, skipNA: Boolean = skipNA
69
69
error(" Cannot find unified number type for $numberTypes " )
70
70
}
71
71
this .convertToUnifiedNumberType(unifiedType)
72
- .mean (unifiedType, skipNA)
72
+ .meanOrNull (unifiedType, skipNA)
73
73
}
74
74
75
75
// this means the sequence is empty
@@ -79,43 +79,43 @@ internal fun <T : Number> Sequence<T>.mean(type: KType, skipNA: Boolean = skipNA
79
79
}
80
80
}
81
81
82
- internal fun Sequence<Double>.mean (skipNA : Boolean = skipNA_default): Double {
82
+ internal fun Sequence<Double>.meanOrNull (skipNA : Boolean = skipNA_default): Double? {
83
83
var count = 0
84
84
var sum: Double = 0 .toDouble()
85
85
for (element in this ) {
86
86
if (element.isNaN()) {
87
87
if (skipNA) {
88
88
continue
89
89
} else {
90
- return Double . NaN
90
+ return null
91
91
}
92
92
}
93
93
sum + = element
94
94
count++
95
95
}
96
- return if (count > 0 ) sum / count else Double . NaN
96
+ return if (count > 0 ) sum / count else null
97
97
}
98
98
99
99
@JvmName(" meanFloat" )
100
- internal fun Sequence<Float>.mean (skipNA : Boolean = skipNA_default): Double {
100
+ internal fun Sequence<Float>.meanOrNull (skipNA : Boolean = skipNA_default): Double? {
101
101
var count = 0
102
102
var sum: Double = 0 .toDouble()
103
103
for (element in this ) {
104
104
if (element.isNaN()) {
105
105
if (skipNA) {
106
106
continue
107
107
} else {
108
- return Double . NaN
108
+ return null
109
109
}
110
110
}
111
111
sum + = element
112
112
count++
113
113
}
114
- return if (count > 0 ) sum / count else Double . NaN
114
+ return if (count > 0 ) sum / count else null
115
115
}
116
116
117
117
@JvmName(" bigIntegerMean" )
118
- internal fun Sequence<BigInteger>.mean (): BigDecimal ? {
118
+ internal fun Sequence<BigInteger>.meanOrNull (): BigDecimal ? {
119
119
var count = 0
120
120
val sum = sumOf {
121
121
count++
@@ -125,7 +125,7 @@ internal fun Sequence<BigInteger>.mean(): BigDecimal? {
125
125
}
126
126
127
127
@JvmName(" bigDecimalMean" )
128
- internal fun Sequence<BigDecimal>.mean (): BigDecimal ? {
128
+ internal fun Sequence<BigDecimal>.meanOrNull (): BigDecimal ? {
129
129
var count = 0
130
130
val sum = sumOf {
131
131
count++
@@ -135,65 +135,65 @@ internal fun Sequence<BigDecimal>.mean(): BigDecimal? {
135
135
}
136
136
137
137
@JvmName(" doubleMean" )
138
- internal fun Iterable<Double>.mean (skipNA : Boolean = skipNA_default): Double = asSequence().mean (skipNA)
138
+ internal fun Iterable<Double>.meanOrNull (skipNA : Boolean = skipNA_default): Double? = asSequence().meanOrNull (skipNA)
139
139
140
140
@JvmName(" floatMean" )
141
- internal fun Iterable<Float>.mean (skipNA : Boolean = skipNA_default): Double = asSequence().mean (skipNA)
141
+ internal fun Iterable<Float>.meanOrNull (skipNA : Boolean = skipNA_default): Double? = asSequence().meanOrNull (skipNA)
142
142
143
143
@JvmName(" bigDecimalMean" )
144
- internal fun Iterable<BigDecimal>.mean (): BigDecimal ? = asSequence().mean ()
144
+ internal fun Iterable<BigDecimal>.meanOrNull (): BigDecimal ? = asSequence().meanOrNull ()
145
145
146
146
@JvmName(" bigIntegerMean" )
147
- internal fun Iterable<BigInteger>.mean (): BigDecimal ? = asSequence().mean ()
147
+ internal fun Iterable<BigInteger>.meanOrNull (): BigDecimal ? = asSequence().meanOrNull ()
148
148
149
149
@JvmName(" intMean" )
150
- internal fun Iterable<Int>.mean (): Double =
150
+ internal fun Iterable<Int>.meanOrNull (): Double? =
151
151
if (this is Collection ) {
152
- if (size > 0 ) sumOf { it.toDouble() } / size else Double . NaN
152
+ if (size > 0 ) sumOf { it.toDouble() } / size else null
153
153
} else {
154
154
var count = 0
155
155
val sum = sumOf {
156
156
count++
157
157
it.toDouble()
158
158
}
159
- if (count > 0 ) sum / count else Double . NaN
159
+ if (count > 0 ) sum / count else null
160
160
}
161
161
162
162
@JvmName(" shortMean" )
163
- internal fun Iterable<Short>.mean (): Double =
163
+ internal fun Iterable<Short>.meanOrNull (): Double? =
164
164
if (this is Collection ) {
165
- if (size > 0 ) sumOf { it.toDouble() } / size else Double . NaN
165
+ if (size > 0 ) sumOf { it.toDouble() } / size else null
166
166
} else {
167
167
var count = 0
168
168
val sum = sumOf {
169
169
count++
170
170
it.toDouble()
171
171
}
172
- if (count > 0 ) sum / count else Double . NaN
172
+ if (count > 0 ) sum / count else null
173
173
}
174
174
175
175
@JvmName(" byteMean" )
176
- internal fun Iterable<Byte>.mean (): Double =
176
+ internal fun Iterable<Byte>.meanOrNull (): Double? =
177
177
if (this is Collection ) {
178
- if (size > 0 ) sumOf { it.toDouble() } / size else Double . NaN
178
+ if (size > 0 ) sumOf { it.toDouble() } / size else null
179
179
} else {
180
180
var count = 0
181
181
val sum = sumOf {
182
182
count++
183
183
it.toDouble()
184
184
}
185
- if (count > 0 ) sum / count else Double . NaN
185
+ if (count > 0 ) sum / count else null
186
186
}
187
187
188
188
@JvmName(" longMean" )
189
- internal fun Iterable<Long>.mean (): Double =
189
+ internal fun Iterable<Long>.meanOrNull (): Double? =
190
190
if (this is Collection ) {
191
- if (size > 0 ) sumOf { it.toDouble() } / size else Double . NaN
191
+ if (size > 0 ) sumOf { it.toDouble() } / size else null
192
192
} else {
193
193
var count = 0
194
194
val sum = sumOf {
195
195
count++
196
196
it.toDouble()
197
197
}
198
- if (count > 0 ) sum / count else Double . NaN
198
+ if (count > 0 ) sum / count else null
199
199
}
0 commit comments