VTL Velocity Template Language - Problems with type casting - casting

I have written the VTL below to check to see if variables(attributes) I am getting from my PIM system are not blank. If they are set them to zero. Then mathematically add the two variables.
The problem I am having is they must be strings or treated as string. The result of ($FordR12 + $DodgeR12) is the number concatenated. Example: 58 + 58 = 5858 How do I add these strings mathematically as numbers?
#if(${R12 Sales Rev Ford VDSP}== "")
#set($FordR12 = 0)
#else
#set($FordR12 = ${R12 Sales Rev Ford VDSP})
#end
#if(${R12 Sales Rev Dodge VDSP}== "")
#set($DodgeR12 = 0)
#else
#set($DodgeR12 = ${R12 Sales Rev Dodge VDSP})
#end
#set($Total = ($FordR12 + $DodgeR12))
$Total
I have looked online for ways to type cast the variables, including the VTL online documentation. All have failed so far :(

It seems like your variables are strings, which means VTL will concatenate them instead of adding them together.
You can get access to Integer.parseInt and convert them to Integers first, like this:
#set($Integer = 0)
#if(${R12 Sales Rev Ford VDSP} == "")
#set($FordR12 = 0)
#else
#set($FordR12 = $Integer.parseInt(${R12 Sales Rev Ford VDSP}))
#end
#if(${R12 Sales Rev Dodge VDSP} == "")
#set($DodgeR12 = 0)
#else
#set($DodgeR12 = $Integer.parseInt(${R12 Sales Rev Dodge VDSP}))
#end
#set($Total = ($FordR12 + $DodgeR12))
$Total
Though it doesn't appear you're using an AWS service here, here's a Mapping Tool link which is still helpful for trying these things out: https://mappingtool.dev/app/apigateway/b08ed9b630114561134d7a41315d817c
Note that I've changed your variable name because it's not valid in standard VTL.

Related

How do I create calculated column in power bi?

I am new to Power BI and was wondering if someone can help me.
I have a table
A B Status
---------------------------
Asset1 B1 Compliant
Asset1 B2 N/A
Asset2 B1 Non- Compliant
Asset2 B2 Compliant
Asset3 B1 Compliant
Asset3 B2 Compliant
I have to find the Asset which are 100% compliant(Count of Asset where status of all the rows of Column B is Compliant and not non Compliant and we need to ignore N/A.
Out put I want
A 100%Compliant
Asset1 Y
Asset2 N
Asset3 Y
Thanks
You can create an extra column in your table:
100% Cpmpliant =
var asset = Compliant[A]
var allRows = CALCULATE(COUNTROWS(Compliant); FILTER(Compliant; Compliant[A] = asset && Compliant[Status] <> "N/A"))
var compliantRows = CALCULATE(COUNTROWS(Compliant); FILTER(Compliant; Compliant[A] = asset && Compliant[Status] = "Compliant"))
return if (allRows = compliantRows; "Y";"N")
This calculates the rows of the asset without the N/A and compares it against teh rowcount of the compliant. If this is equal, they are all compliant-
Next you can create a visual with two columns ass below:
Edited:
You can create a measure:
IsCompliant =
VAR NumNonCompliant = CALCULATE(COUNTAX('Table', [B]), 'Table'[Status] = "Non - Compliant")
RETURN IF(NumNonCompliant = 0, "Y", "N")
The variable NumConCompliant calculates the number of rows with status = "Non - Compliant". Then it is compared with 0 to find any non-compliance.
Then the measure returns the state of "A" in the given context. This gives you the flexibility of assigning compliance measure to a combination of assets. For example if you filter data on "A = Asset1", the result would be "Y", and (A = Asset1 || A = Asset2) results in a "N". (Since the combination of Asset1 & Asset2 are non-compliant).
Refer to this doc about measures and contexts.

Crystal Report converting value to number with symbol

I have an issue with a Crystal Report that I'm creating. I am using fields from a database and am pulling in the result value where the analysis field is equal to certain values.
In the condition the first check looks at the analysis field and checks if its equal to "Conf". The result for this is "<10"
The second check looks at the analysis field and checks if its equal to "Original". The result for this is "20".
I want the results to display in the order above however with the following basic logic it returns the result of 20.
if analysis = "conf" then result
else if analysis = "Original" then result
I was having this issue with multiple records however solved it by converting both results to numbers (toNumber(Result)). However this record has the less than symbol contained within the field value which causes the conf result to "be skipped" and will display the original result instead. I've tried a few things without success. Here is the code for the condition of where I'm at below. I fell this is way to complex logic but I've just added to it as I've had ideas and it shows what I've tried.
if {UNITS} = "CFU_G" then
if {ANALYSIS} = "CONF" and
{RESULT}="" or
{RESULT} = "0" then 0
else if {ANALYSIS} = "CONF"
then if isNumeric({RESULT}) then
tonumber({RESULT}) else
tonumber(Replace ({RESULT}, "<", ""))
else
if {UNITS} = "CFU_G" then
if {ANALYSIS} = "Original" and
{RESULT}="" or
{RESULT} = "0" then 0
else if {ANALYSIS} = "Original"
then if isNumeric({RESULT}) then
tonumber({RESULT}) else
tonumber(Replace ({RESULT}, "<", ""))
Thanks,
Tom
This was the solution I came up with.
Field 1
whileprintingrecords;
stringvar vResult := "";
Field 2
whileprintingrecords;
stringvar vResult;
vResult := if {RESULT.UNITS} = "CFU_G"
and {RESULT.ANALYSIS} = "CRA_LIS_ENU_CONF_MPCRAM29"
then {RESULT.FORMATTED_ENTRY}
else if {RESULT.ANALYSIS} = "CRA_LIST_ENU_MPCRAM29"
and {RESULT.UNITS} = "CFU_G"
and vResult = ""
then {RESULT.FORMATTED_ENTRY}
Field 3
whileprintingrecords;
stringvar vResult;
vResult;

Retrieve values from an array - get "cannot call value of non-function type String"

I'm trying to retrieve a value from an array, based on an index parsed from a string of digits. I'm stuck on this error, and the other answers to similar questions in this forum appear to be for more advanced developers (this is my first iOS app).
The app will eventually look up weather reports ("MAFOR" groupings of 5 digits each) from a web site, parse each group and lookup values from arrays for wind direction, speed, forecast period etc using each character.
The playground code is below, appreciate any help on where I am going wrong (look for ***)
//: Playground - noun: a place where people can play
import UIKit
var str = "Hello, playground"
// create array for Forecast Period
let forecastPeriodArray = ["Existing conditions at beginning","3 hours","6 hours","9 hours","12 hours","18 hours","24 hours","48 hours","72 hours","Occasionally"]
// create array for Wind Direction
let windDirectionArray = ["Calm","Northeast","East","Southeast","South","Southwest","West","Northwest","North","Variable"]
// create array for Wind Velocity
let windVelocityArray = ["0-10 knots","11-16 knots","17-21 knots","22-27 knots","28-33 knots","34-40 knots","41-47 knots","48-55 knots","56-63 knots","64-71 knots"]
// create array for Forecast Weather
let forecastWeatherArray = ["Moderate or good visibility (> 3 nm.","Risk of ice accumulation (temp 0C to -5C","Strong risk of ice accumulkation (air temp < -5C)","Mist (visibility 1/2 to 3 nm.)","Fog (visibility less than 1/2 nm.)","Drizzle","Rain","Snow, or rain and snow","Squally weather with or without showers","Thunderstorms"]
// retrieve full MAFOR line of several information groups (this will be pulled from a web site)
var myMaforLineString = "11747 19741 13757 19751 11730 19731 11730 13900 11630 13637"
// split into array components wherever " " is encountered
var myMaforArray = myMaforLineString.components(separatedBy: " ")
let count = myMaforArray.count
print("There are \(count) items in the array")
// Go through each group and parse out the needed digits
for maforGroup in myMaforArray {
print("MAFOR group \(maforGroup)")
// get Forecast Period
var idx = maforGroup.index(maforGroup.startIndex, offsetBy: 1)
var periodInt = maforGroup[idx]
print("periodInt is \(periodInt)")
// *** here is where I am stuck... trying to use the periodInt index value to retrieve the description from the ForecastPeriodArray
var periodDescription = forecastPeriodArray(periodInt)
print("Forecast period = (forecastPeriodArray(periodInt)")
// get Wind Direction
idx = maforGroup.index(maforGroup.startIndex, offsetBy: 2)
var directionInt = maforGroup[idx]
print("directionInt is \(directionInt)")
// get Wind Velocity
idx = maforGroup.index(maforGroup.startIndex, offsetBy: 3)
var velocityInt = maforGroup[idx]
print("velocityInt is \(velocityInt)")
// get Weather Forecast
idx = maforGroup.index(maforGroup.startIndex, offsetBy: 4)
var weatherInt = maforGroup[idx]
print("weatherInt is \(weatherInt)")
}
#shallowThought was close.
You are trying to access an array by its index, therefore use the array[index] notation. But your index has to be of the correct type. forecastPeriodArray[periodInt] therefore does not work since periodInt is not an Int as the name would suggest. Currently it is of type Character which does not make much sense.
What you are probably trying to achieve is convert the character to an integer and use that to access the array:
var periodInt = Int(String(maforGroup[idx]))!
You might want to add error handling for the case when the character does not actually represent an integer.

Dropping entire subject if single observation meets criterion in panel data

I have some panel data of the form...
id | amount
-----------
1 | 10
1 | 10
1 | 100
2 | 10
2 | 15
2 | 10
3 | 100
What I'm looking to do seems like it should be fairly simple, but my experience with Stata is limited and I'm used to programming in languages similar to C/Java. Essentially, I want to drop an entire person (id) if any of their individual observations ever exceed a certain amount. So let's say I set this amount to 50, I want to drop all the observations from id 1 and id 3 such that the data will then only contain observations from id 2.
The pseudo-code in Java would be fairly straightforward...
for(int i = 0; i < dataset_length; i++) {
if dataset[i].amount > 50 {
int drop_id = dataset[i].id;
for(int j = 0; j < dataset_length; j++) {
if dataset[j].id == drop_id {
delete observation
}
}
}
}
What would the Stata equivalent of something akin to this be? I'm surely missing something and making it more complicated than it ought to be, but I cannot figure it out.
If there are no missings on amount this is just
bysort id (amount) : drop if amount[_N] > 50
If there are missings, then
gen ismissing = -missing(amount)
bysort id (ismissing amount): drop if amount[_N] > 50 & amount[_N] < .
would be one kind of check, although it's hard to see how the missings could be interesting or useful.
The machinery here (for one introduction see here) in effect builds in a loop over identifiers, and over the observations for each identifier. Literal translation using models from mainstream programming languages could only result in lengthier and less efficient code.

Use carryforward with dynamic condition to limit carry forward time interval

I am using carryforward (ssc install carryforward) to fill in missing observations. Some of my data are annual and I want to use them for subsequent monthly observations, but only if the carried forward data are less than two years old. Can I achieve this logic with the dynamic_condition() option, particularly using #? I have to complete this for many variables, and would like to avoid a lot of variable generation and dropping (and really I'd like to know if it's possible).
The following "manual" solution works, but can I replicate it on the fly with dynamic_condition()? My attempts below fail.
/* generate data with observation every June */
clear
set obs 100
generate date_ym = ym(2001, 1) + (_n - 1)
format date_ym %tm
generate date_m = month(dofm(date_ym))
generate x = runiform() if (date_m == 6) & !inlist(_n, 30, 42)
/* carryforward (ssc install carryforward), "manual" solution */
egen date_m2 = group(date_ym) if !missing(x)
carryforward date_m2, replace
bysort date_m2 (date_ym): generate date_m3 = cond(_n > 24, ., date_m2)
carryforward x if !missing(date_m3), gen(x_cf)
tsset date_ym
list, sep(12)
/* can I replicate this with dynamic_condition() option? */
/* no time series operators with # */
/* carryforward x, gen(x_cf2) dynamic_condition(sum(d.# == 0) < 24) */
/* x_cf2: d.x_cf2 invalid name */
/* second # doesn't work */
/* carryforward x, gen(x_cf3) dynamic_condition(sum(# == #[_n - 1]) < 24) */
/* x_cf3: equation [_n-1] not found */
Disclosure: I don't use carryforward (SSC), but that's because I tend to think back to the principles as I understand them, as documented here.
To do this, you need to keep a record not only of previous non-missing values but also of the dates when a variable was last not missing. This arose previously: see this answer
The essence of a simpler approach is here:
clear
set seed 2803
set obs 100
generate date_ym = ym(2001, 1) + (_n - 1)
format date_ym %tm
generate x = runiform() if inlist(_n, 30, 42)
gen last = date_ym if !missing(x)
replace last = last[_n-1] if missing(last)
replace x = x[_n-1] if missing(x) & (date_ym - last) < 24
The generalisation to panels is using by: and the generalisation to multiple variables uses a foreach loop. If the dates of missing values can be different for different variables, that mostly just shifts the loop.
Schematically, suppose we are cycling over an arbitary varlist and that the dates of missing values differ, but we use the rule of using the last value within 24 months.
gen last = .
quietly foreach v of varlist <varlist> {
replace last = cond(!missing(`v'), date_ym, .)
replace last = last[_n-1] if missing(last)
replace `v' = `v'[_n-1] if missing(`v') & (date_ym - last) < 24
}