-
Notifications
You must be signed in to change notification settings - Fork 51
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* - When ordering by the variable which has same values, need also check own values. Add test. - Add new tests: check ordering in data, data with null values. * Add merging of groups after stat applying according to ordering settings. * Minor code improvement. * Add checking of order direction: require -1 or 1. Fix comparator for groups. Add new tests. * Add order settings from discrete to non-discrete mappings. Fix test. * Code cleanup. * Apply order options from layer's discrete variable to plot's non-discrete variable and vice versa. Add test. Update notebook. * Update the data in tests (it will improve examples with 'count'). Add new examples in the notebook. * Add 'sum' as aggregate operation for position='stack'. * Update notebook: add sampling_pick + order_by='..count..'. * Make class GroupMerger as a top-level internal class.
- Loading branch information
1 parent
99bc39e
commit df2c7cd
Showing
12 changed files
with
1,153 additions
and
160 deletions.
There are no files selected for viewing
479 changes: 423 additions & 56 deletions
479
docs/examples/jupyter-notebooks-dev/ordering_examples.ipynb
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
...ilder-portable/src/commonMain/kotlin/jetbrains/datalore/plot/builder/data/GroupsMerger.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* | ||
* Copyright (c) 2021. JetBrains s.r.o. | ||
* Use of this source code is governed by the MIT license that can be found in the LICENSE file. | ||
*/ | ||
|
||
package jetbrains.datalore.plot.builder.data | ||
|
||
import jetbrains.datalore.plot.base.Aes | ||
import jetbrains.datalore.plot.base.DataFrame | ||
import jetbrains.datalore.plot.builder.VarBinding | ||
|
||
internal class GroupsMerger { | ||
private var myOrderSpecs: List<DataFrame.OrderSpec>? = null | ||
private val myOrderedGroups = ArrayList<Group>() | ||
|
||
fun initOrderSpecs( | ||
orderOptions: List<OrderOptionUtil.OrderOption>, | ||
variables: Set<DataFrame.Variable>, | ||
bindings: List<VarBinding>, | ||
aggregateOperation: ((List<Double?>) -> Double?)? | ||
) { | ||
if (myOrderSpecs != null) return | ||
myOrderSpecs = orderOptions | ||
.filter { orderOption -> | ||
// no need to reorder groups by X | ||
bindings.find { it.variable.name == orderOption.variableName && it.aes == Aes.X } == null | ||
} | ||
.map { OrderOptionUtil.createOrderSpec(variables, bindings, it, aggregateOperation) } | ||
} | ||
|
||
fun getResultSeries(): HashMap<DataFrame.Variable, MutableList<Any?>> { | ||
val resultSeries = HashMap<DataFrame.Variable, MutableList<Any?>>() | ||
myOrderedGroups.forEach { group -> | ||
group.df.variables().forEach { variable -> | ||
resultSeries.getOrPut(variable, ::ArrayList).addAll(group.df[variable]) | ||
} | ||
} | ||
return resultSeries | ||
} | ||
|
||
fun getGroupSizes(): List<Int> { | ||
return myOrderedGroups.map(Group::groupSize) | ||
} | ||
|
||
inner class Group( | ||
val df: DataFrame, | ||
val groupSize: Int | ||
) : Comparable<Group> { | ||
override fun compareTo(other: Group): Int { | ||
fun compareGroupValue(v1: Any?, v2: Any?, dir: Int): Int { | ||
// null value is always greater - will be at the end of the result | ||
if (v1 == null && v2 == null ) return 0 | ||
if (v1 == null) return 1 | ||
if (v2 == null) return -1 | ||
return compareValues(v1 as Comparable<*>, v2 as Comparable<*>) * dir | ||
} | ||
fun getValue( | ||
df: DataFrame, | ||
variable: DataFrame.Variable, | ||
aggregateOperation: ((List<Double?>) -> Double?)? = null | ||
): Any? { | ||
return if (aggregateOperation != null) { | ||
require(df.isNumeric(variable)) { "Can't apply aggregate operation to non-numeric values" } | ||
aggregateOperation.invoke(df.getNumeric(variable).requireNoNulls()) | ||
} else { | ||
// group has no more than one unique element | ||
df[variable].firstOrNull() | ||
} | ||
} | ||
|
||
myOrderSpecs?.forEach { spec -> | ||
var cmp = compareGroupValue( | ||
getValue(df, spec.orderBy, spec.aggregateOperation), | ||
getValue(other.df, spec.orderBy, spec.aggregateOperation), | ||
spec.direction | ||
) | ||
if (cmp == 0) { | ||
// ensure the order as in the legend | ||
cmp = compareGroupValue( | ||
getValue(df, spec.variable), | ||
getValue(other.df, spec.variable), | ||
spec.direction | ||
) | ||
} | ||
if (cmp != 0) { | ||
return cmp | ||
} | ||
} | ||
return 0 | ||
} | ||
} | ||
|
||
fun addGroup(d: DataFrame, groupSize: Int) { | ||
val group = Group(d, groupSize) | ||
val indexToInsert = findIndexToInsert(group) | ||
myOrderedGroups.add(indexToInsert, group) | ||
} | ||
|
||
private fun findIndexToInsert(group: Group): Int { | ||
if (myOrderSpecs.isNullOrEmpty()) { | ||
return myOrderedGroups.size | ||
} | ||
var index = myOrderedGroups.binarySearch(group) | ||
if (index < 0) index = index.inv() | ||
return index | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.