You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlin的Lets-Plot中为股票成本线按购买状态设置双色?

优化股票交易图表线段着色的Kotlin实现方案

问题根源

直接将color映射到isPurchased布尔值时出现线条间隙,是因为状态切换时相邻点属于不同分组,绘图库不会绘制跨分组的线段。而多geomLine方案会重复加载数据,导致内存占用高、性能差。

优化方案

通过预处理数据拆分连续状态段,配合单geomLine的分组映射实现无间隙着色,同时避免数据重复。核心思路是:

  • 将连续同状态的点划分为独立线段组
  • 状态切换时,将切换点同时加入前后两个组,保证线段衔接
  • 用group映射区分不同线段组,color映射控制颜色

Kotlin实现代码(基于Lets-Plot库)

import org.jetbrains.letsPlot.letsPlot
import org.jetbrains.letsPlot.geom.geomLine
import org.jetbrains.letsPlot.scale.scaleColorManual
import org.jetbrains.letsPlot.aes

// 数据类定义
data class DataPoint(val index: Int, val cost: Double, val isPurchased: Boolean)

fun main() {
    // 示例原始数据
    val costs = listOf(100.0, 101.0, 102.0, 103.0, 102.5, 101.5, 100.5)
    val isPurchased = listOf(false, false, true, true, true, false, false)

    // 合并为带索引的数据点列表
    val dataPoints = costs.mapIndexed { index, cost ->
        DataPoint(index, cost, isPurchased[index])
    }

    // 拆分连续状态段,处理衔接点
    val segments = mutableListOf<List<DataPoint>>()
    if (dataPoints.isEmpty()) return

    var currentSegment = mutableListOf(dataPoints.first())
    var currentState = dataPoints.first().isPurchased

    for (i in 1 until dataPoints.size) {
        val point = dataPoints[i]
        if (point.isPurchased == currentState) {
            currentSegment.add(point)
        } else {
            // 切换点加入前一段,保证衔接
            currentSegment.add(point)
            segments.add(currentSegment)
            // 初始化新段,以切换点为起点
            currentSegment = mutableListOf(point)
            currentState = point.isPurchased
        }
    }
    segments.add(currentSegment)

    // 转换为绘图所需的扁平化数据结构
    val plotData = segments.flatMapIndexed { segmentId, points ->
        points.map { point ->
            mapOf(
                "x" to point.index,
                "y" to point.cost,
                "isPurchased" to point.isPurchased,
                "segmentId" to segmentId
            )
        }
    }

    // 绘制图表
    val plot = letsPlot(plotData) +
            geomLine(
                mapping = aes(x = "x", y = "y", color = "isPurchased", group = "segmentId"),
                size = 1.2
            ) +
            scaleColorManual(
                values = mapOf(false to "#00ff00", true to "#ff0000"),
                labels = mapOf(false to "未购买", true to "已购买")
            )

    plot.show()
}

方案优势

  • 仅使用单个geomLine,避免多图层带来的内存浪费和性能损耗
  • 通过预处理保证线段无间隙衔接,符合视觉需求
  • 数据仅在状态切换点少量重复,远优于多图层的数据重复问题

内容的提问来源于stack exchange,提问作者Roman Aymaletdinov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 13:13:24