How to apply if statement to calcuate integer value inside a group question in Enketo(KoboToolbox)? - xls

I am building a survey form through KoboToolbox. The web forms are Enketo based. I have some questions of the following type (before comma is first column and first row is data titles in XLSform format):
type, name
begin_group, group_farmexpenses_q5
note, group_farmexpenses_q5_note
integer, group_farmexpenses_q5_p1
text, group_farmexpenses_q5_column_1
end_group,
begin_group, group_farmexpenses_q5_1
note, group_farmexpenses_q5_1_note
integer, group_farmexpenses_q5_1_p1
text, group_farmexpenses_q5_1_column_1
end_group,
What i want to do is apply if statement for the integer values inside these two groups, however I get error. Here is what I do to apply if-statement :
if(${group_farmexpenses_q5_p1}=999, 0, ${group_farmexpenses_q5_p1})
if(${group_farmexpenses_q5_1_p1}=999, 0, ${group_farmexpenses_q5_1_p1})
since the above are calculate statements and each one is referred to as "expense1" and "expense2"
i then just add them
${expense1} + ${expense2}
I get error message:
if({group_farmexpenses_q5_1_p1} = 999, 0,
/model/instance[1]/data/group_wx0mk24/group_farmexpenses_q5_1/group_farmexpenses_q5_1_p1
), message: The expression is not a legal expression. (line:
undefined, character: undefined)
Any ideas how to fix this? I think there should be an easy fix but I don't know much about XLSform structures.

Proposed solution through online search for #Ziaw. Instead of first conditioning and then adding, both can be done in one step:
calculated data field compute this
if(${fexp_q1} = 999, 0, ${fexp_q1}) + if(${fexp_q2} = 999, 0,
${fexp_q2})

Related

I try to write formula in notion, that display in cell max value from another cell. But notion not allow me to set a circular dependency in formulas

maxDebt - it is column with formula.
lastDebt - it is column with data.
I tried to write maxDebt formula like this:
if(
prop("lastDebt") == 0,
0,
if(
prop("lastDebt") > prop("maxDebt"),
prop("lastDebt"),
prop("maxDebt")
)
)
And notion ask me error: "Property maxDebt creates a circular dependency."
How to resolve this task differently?

Remove conditional sequence from string in R

I have a sequence encoded in a string, but one type of step in this sequence is entirely conditional on a previous step.
When this occurs, I'd like to remove the previous step.
For example, in the case:
"alpha_i, bravo_i, alpha_i, alpha_c, charlie_i, bravo_i, bravo_c,
alpha_i, delta_c"
those steps where a *_c event occurs directly after an *_i event, I'd like to have the *_i event removed, the desired result being:
"alpha_i, bravo_i, alpha_c, charlie_i, bravo_c, alphai_i,
delta_c"
In other words,
"alpha_i, alpha_c" goes to just "alpha_c"
"bravo_i, bravo_c" goes to just "bravo_c",
but we do not change "alpha_i, delta_c" because they are a different event name.
I think the syntax would use the gsub function, but I don't know how to match the prefixed term either side of the comma, and would appreciate some help.
*In addition to the point raised below; yes there will be many different examples of event names, not just the two being replaced here.
Try this:
wds <- c("alpha_i", "bravo_i", "alpha_i", "alpha_c", "charlie_i", "bravo_i", "bravo_c", "alpha_i", "delta_c")
wds[cumsum(rle(as.character(substr(wds, 1, gregexpr('_', wds))))$lengths)]
Alternatively, if your vector is of length 1, try this:
wds <- c("alpha_i, bravo_i, alpha_i, alpha_c, charlie_i, bravo_i, bravo_c, alpha_i, delta_c")
wds_split <- unlist(strsplit(wds, ', '))
wds_split[cumsum(rle(as.character(substr(wds_split, 1, gregexpr('_', wds_split))))$lengths)]

Remove sections of a string or parse data?

I have a long string of data and I'm trying to pick out one small piece of it. The position in the string changes all the time. A sample of the data is below. I have researched strip and parse, but I'm thinking strip is the wrong choice, but parse might do it.
Data: {'DriverCarSLFirstRPM': 6000.0, 'DriverCarFuelMaxLtr': 44.987, 'DriverCarMaxFuelPct': 0.3, 'Drivers': [{'CarIsAI': 0, 'LicSubLevel': 1, 'TeamID': 0}
I'm trying to get the value for DriverCarFuelMaxLtr. Should I be trying to strip the data before and after that value, or is there a way to seperate the file at the commas and then read the values?
Your JSON was invalid to start with.
This has now been validated:
{
"DriverCarSLFirstRPM": 6000.0,
"DriverCarFuelMaxLtr": 44.987,
"DriverCarMaxFuelPct": 0.3,
"Drivers": [{
"CarIsAI": 0,
"LicSubLevel": 1,
"TeamID": 0
}]
}
This should help you get started:
import json
data = '{"DriverCarSLFirstRPM": 6000.0, "DriverCarFuelMaxLtr": 44.987,"DriverCarMaxFuelPct": 0.3,"Drivers": [{"CarIsAI": 0,"LicSubLevel": 1,"TeamID": 0}]}'
info = json.loads(data)
# To get the value of "DriverCarFuelMaxLtr"
print(info.get('DriverCarFuelMaxLtr'))
Output: 44.987
It looks like you have a stringified json object. You could look into Json.loads().
Or if I am mistaken and for some reason you can not transform it into a dictionary I would just use regex (regular expressions).
If you don't know about regex you can look at this guide and learn how to use them in python.

IcCube - Treemap with Parent/Child dimension

I currently try to build a google treemap chart in IcCube. Do I do this using a Multi Level dimension and defining every Level of drilldown separately (as shown
here and here), everything works fine.
What I would like to do is using a Parent/Child dimension and telling the treemap, just to go down this hierarchy when drilling into the treemap chart.
Is that possible?
Here is the (not working) MDX I used, where [categories] is the Parent/Child dimension:
WITH
MEMBER [category_name] as [categories].[categories].currentmember.name
SELECT
{[category_name],[Measures].[count_clicks]} on 0,
non empty [categories].[categories] on 1
FROM
[Cube]
Treemap is a tricky visualization. You need to define the two first columns as defining the parent/child relation. For example :
'Global', null
'America', 'Global'
'Europe', 'Global'
'Brazil', 'America'
The first column is by construction the Axis(1) name, so the seconds has to be the name of the parent and not the name of the member. Something like :
MEMBER [parent_name] as IIF( [categories].[categories].currentmember is [categories].[categories].[ALL],
NULL,
[categories].[categories].currentmember.parent.name )
That you can use as :
WITH
MEMBER [parent_name] as IIF( [categories].[categories].currentmember is [categories].[categories].[ALL],NULL,[categories].categories].currentmember.parent.name )
SELECT
{[parent_name],[Measures].[count_clicks]} on 0,
non empty [categories].[categories] on 1
FROM
[Cube]
This should work better.
Hope it helps.
After struggling for a while with my own data, I took the IcCube example of the parent/child Dimension (http://www.iccube.com/support/documentation/user_guide/schemas_cubes/dim_parentchild.php). Then I tried your example:
WITH
MEMBER [parent_name] as IIF( [dim (ALL)].[Hierarchy].currentmember
is [dim (ALL)].[Hierarchy].[ALL],'',
[dim (ALL)]. [Hierarchy].currentmember.parent.name )
SELECT
{[parent_name],[Measures].[value]} on 0,
non empty [dim (ALL)].[Hierarchy] on 1
FROM
[Cube]
(The NULL value had to be replaced by '')
The first dimension works, but if I try to drill into the map, the system tells me, that there is no row with id 'World'. Do you have any ideas, how to fix that?
EDIT:
After using real names in the parent/child dimension instead of ids (child: Spain; parent: Europe, value: 3) and replacing [dim (ALL)].[Hierarchy] with [dim (ALL)].[Hierarchy].members() in the code, I got a treemap working so far:
WITH
MEMBER [parent_name] as IIF( [dim (ALL)].[Hierarchy].currentmember
is [dim (ALL)].[Hierarchy],'',
[dim (ALL)].[Hierarchy].currentmember.parent.name )
SELECT
{[parent_name],[Measures].[value]} on 0,
non empty [dim (ALL)].[Hierarchy].members() on 1
FROM
[Cube]
Now after drilling down to the next level, the is an error message 'failed to find row with id "Europe"'. And I added a 3 Level into my data (child: Madrid; parent: Spain, value: 5), but I am unable to go to this level. Clicking on "Spain" doesn't change anything.

Numpy: Referencing an array column in another array without copies

Using numpy, say you have a 3D array called img filled with pixel values and you want to build an array filled with zeros everywhere but on a given color channel. For example say that img[0,0]=(42,84,126) in the output array dedicated to the red channel I'd like to have output_red[0,0]=(42,0,0).
This can be trivially done like this for example:
output_red=np.zeros(img.shape,dtype=img.dtype)
output_red[...,0]=img[...,0]
However I'm still trying to figure out if there is a way to do it:
without changing anything in img (otherwise I won't be able to extract the other color channels)
without copying data from img to output at some point.
This can be trivially done in C using pointers but as numpy.ndarrays must be continuous in memory there is IMHO no hope to do so with array slicing. Array masks are not working either as their filled() method copies the data and I have to admit I have no other idea.
Do you know some magic trick in numpy to do this or is it hopeless ?
Thanks
As the question is phrased, the answer is no.
(If you explain more about your goal and how you'd eventually use the output array, we might be able to suggest alternative solutions, e.g. that the output array doesn't have to be an array at all, or that it doesn't have to have the same shape as the input.)
Numpy ndarrays which own their data hold a structure which is continuous in memory, and is not shared with other arrays which own their data. The way to "share" is using views (i.e. arrays which don't own their data) (e.g. when slicing), but a view refers to a single other array, it cannot refer to segments of multiple ndarrays.
Depending on your use case, it might be acceptable to create a bigger ndarray containing all the additional zeros, and then slice it to get the "color" views you want.
Something like:
arr = np.array(..., shape = (N,M,3*3))
real_colors_arr = arr[..., :3] # all the rest are zeros
red_arr = arr[..., 0::3]
green_arr = arr[..., 1::3]
blue_arr = arr[..., 2::3]
#shx2 answer was the right one, for posterity here is how I did it if anybody else has this problem one day:
# allocate a new array to store the image data and
# get a view on each channel without copies
# - width and height are the same as frame
# - contains 9 entries for each pixel
# - each entry organized like that: blue 0 0 0 green 0 0 0 red
frame_container=np.zeros((h, w, depth*3), dtype=np.uint8)
frame=frame_container[...,::4]
#get a view on each channel as (b,0,0), (0,g,0), (0,0,r)
channels={"blue":frame_container[...,:3],
"green":frame_container[...,3:6],
"red":frame_container[...,6:]}
This won't explicitly copy nor do in-situ changes as mentioned in the two requirements, but will use altogether new placeholder for the output -
output_red = np.einsum('ijk,k->ijk',img,np.array([1,0,0]))
Sample run -
In [56]: img
Out[56]:
array([[[ 50, 83, 185],
[ 83, 116, 125],
[ 43, 179, 11]],
[[108, 160, 122],
[ 55, 206, 96],
[134, 149, 232]]])
In [57]: np.einsum('ijk,k->ijk',img,np.array([1,0,0]))
Out[57]:
array([[[ 50, 0, 0],
[ 83, 0, 0],
[ 43, 0, 0]],
[[108, 0, 0],
[ 55, 0, 0],
[134, 0, 0]]])

Resources