Kotlin Dataframe:如何保留Double类型格式化百分比列
问题:Kotlin Dataframe保留Double类型同时格式化百分比列
我是Kotlin Dataframe的新手,相关文档不够完善。我有一个包含项目计数和计算得出的占比数据的Dataframe,代码如下:
countsDF.groupBy("type").count().add("percentage") { "count"<Double>() / totalVerifications }.sortBy {it["count"].desc() }
生成的Dataframe如下:
| type | count | percentage |
|---|---|---|
| Type1 | 187026 | 0.966103 |
| Type2 | 4546 | 0.023483 |
| Type3 | 1596 | 0.008244 |
| Type4 | 223 | 0.001152 |
| Type5 | 142 | 0.000734 |
| Type6 | 54 | 0.000279 |
| Type7 | 1 | 0.000005 |
问题:能否将percentage列格式化为显示两位小数和百分号,同时保留Double类型?
我尝试通过添加新列实现显示效果,但得到的是String类型的列。我认为应该有一种方法可以在保留Double类型的同时指定数字格式,当前尝试的代码如下:
countsDF.groupBy("type").count().add("percentage") { DecimalFormat("0.0%").format("count"<Double>() / totalVerifications) }.sortBy {it["count"].desc() }
生成的结果:
| type | count | percentage |
|---|---|---|
| Type1 | 187026 | 96.6% |
| Type2 | 4546 | 2.3% |
| Type3 | 1596 | 0.8% |
| Type4 | 223 | 0.1% |
| Type5 | 142 | 0.1% |
| Type6 | 54 | 0.0% |
| Type7 | 1 | 0.0% |
解决方案
核心要明确:Double类型仅存储数值,不携带任何格式信息,因此无法让Double列本身"自带"百分号或小数位数格式——格式化操作本质是将数值转换为字符串的过程。要保留Double类型的同时实现格式化显示,需要将数据存储和显示逻辑分开处理:
1. 存储原始百分比数值,显示时格式化
先计算出百分比形式的Double数值(乘以100,比如0.9661转为96.61),保留列的Double类型,在需要展示/输出时再对数值进行格式化:
// 计算百分比数值(乘以100),保留Double类型 val resultDF = countsDF.groupBy("type") .count() .add("percentage") { "count"<Double>() / totalVerifications * 100 } .sortBy { it["count"].desc() } // 输出时格式化:保留两位小数+百分号 resultDF.forEach { row -> val formattedPercent = "%.2f%%".format(row["percentage"]<Double>()) println("${row["type"]} | ${row["count"]} | $formattedPercent") }
输出结果会是:
Type1 | 187026 | 96.61% Type2 | 4546 | 2.35% Type3 | 1596 | 0.82% Type4 | 223 | 0.12% Type5 | 142 | 0.07% Type6 | 54 | 0.03% Type7 | 1 | 0.00%
这样percentage列始终是Double类型,可用于后续的数值计算,仅在显示时转换为带格式的字符串。
2. (可选)自定义包装类(不推荐)
如果非要在Dataframe层面关联格式,可以自定义一个包装类,封装Double值和格式化逻辑,但这会增加代码复杂度,且不符合数值存储的常规做法,仅适合特殊场景:
data class FormattedDouble(val value: Double) { override fun toString(): String = "%.2f%%".format(value * 100) } val resultDF = countsDF.groupBy("type") .count() .add("percentage") { FormattedDouble("count"<Double>() / totalVerifications) } .sortBy { it["count"].desc() }
此时percentage列的类型是FormattedDouble,toString时会输出带格式的字符串,但要注意后续数值计算需要提取value属性。
内容的提问来源于stack exchange,提问作者meshymesh
相关产品推荐
相关产品推荐

