我知道如何获得数字之间的平均值,但是当我尝试采用相同的方法(通过设置变量的属性)从数字和字符串的混合值中获取平均值时,它总是返回异常(而且我知道为什么)。
如何获取具有数字和字符串混合值的column_1的平均值?
column_1
3
4
N/A
3
N/A
意思是说,在第 1 列中,平均值必须为 3.33。
应应用 (3+4+3)/3
公式,两个 N/A
值必须在计算中被忽略/排除。如何做到这一点?
最佳答案
该任务可以分解为几个简单的子任务:
- 从混合类型获取数值。我们应该检查该字段的数值。
- 计算所有数值的平均值(跳过非数值)。
为了解决第一个子任务,我们可以使用 Apache commons-lang 库。 StringUtils.isNumeric(java.lang.CharSequence)方法帮助我们检查该值是否是数字。
为了解决第二个子任务,我们可以使用两个变量 - 第一个用于存储数值,第二个 - 用于计算平均值。
工作示例
数据源
我在此示例中使用了 csv 数据源:
numValue
3
4
N/A
3
N/A
下例中该数据源的数据适配器名称为str_num.csv。文件的第一行被跳过 - 它包含列的名称。
报告模板
我使用Jaspersoft Studio (JSS) 来设计报告模板。 详细区域用于显示数据,摘要区域用于显示平均值。
包含值(数字和非数字)的字段将为 java.lang.String 类型。
第一个变量仅用于存储数值。如果值
,我们将使用 null 初始化变量表达式为:
StringUtils.isNumeric($F{numValue}) ? Integer.valueOf($F{numValue}) : null
此表达式中使用了Java库,这就是为什么我们需要将报表的语言设置为java并添加类StringUtils的导入.
第二个变量将采用平均值计算类型:
<variable name="averageValue" class="java.lang.Double" calculation="Average">
<variableExpression><![CDATA[$V{number}]]></variableExpression>
<initialValueExpression><![CDATA[0]]></initialValueExpression>
</variable>
完整模板:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Average value" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="bee405b0-c35a-442a-841d-f51423c1c797">
<property name="com.jaspersoft.studio.data.defaultdataadapter" value="str_num.csv"/>
<import value="org.apache.commons.lang3.StringUtils"/>
<queryString>
<![CDATA[]]>
</queryString>
<field name="numValue" class="java.lang.String"/>
<variable name="number" class="java.lang.Integer">
<variableExpression><![CDATA[StringUtils.isNumeric($F{numValue}) ? Integer.valueOf($F{numValue}) : null]]></variableExpression>
</variable>
<variable name="averageValue" class="java.lang.Double" calculation="Average">
<variableExpression><![CDATA[$V{number}]]></variableExpression>
<initialValueExpression><![CDATA[0]]></initialValueExpression>
</variable>
<detail>
<band height="30" splitType="Stretch">
<textField>
<reportElement x="0" y="0" width="230" height="30" uuid="9d00d7e3-b9bc-404d-8842-728326a5d2df"/>
<textFieldExpression><![CDATA["Original value: " + $F{numValue}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="230" y="0" width="250" height="30" uuid="4509cae9-3b89-4860-838a-36aa4466fb37"/>
<textFieldExpression><![CDATA["Only numeric value: " + $V{number}]]></textFieldExpression>
</textField>
</band>
</detail>
<summary>
<band height="53">
<staticText>
<reportElement x="0" y="0" width="230" height="30" uuid="937af139-259c-49da-a0d9-191bcf801cca"/>
<text><![CDATA[Average value (non numeric values are skipped):]]></text>
</staticText>
<textField pattern="0.00">
<reportElement x="230" y="0" width="140" height="30" uuid="9abd786b-32ee-4ab1-91dc-851e8bfef0db"/>
<textFieldExpression><![CDATA[$V{averageValue}]]></textFieldExpression>
</textField>
</band>
</summary>
</jasperReport>
输出结果
JSS 中生成的结果如下所示:
如果我们将第一个变量(用于存储数值)的表达式更改为这个:
StringUtils.isNumeric($F{numValue}) ? Integer.valueOf($F{numValue}) : 0
结果将是:
- 它是 5 条记录的平均值,而不是上面第一种情况中的 3 条记录的平均值。
关于java - 如何忽略字段的某些值来获取平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39942525/