How to display only non-zero values in pie-chart? - charts

I am using mpandroid chart to display my data. Here I have 5 xvals(A,B,C,D,E). Every xval has a yval(2.2,0.0,4.4,5.1,0.0,9.0).
I want to only display values on the pie-chart which are non-zero. Is there any way to do this?
So my PieData finally is created like this:
PieData d = new PieData(xVals, ds1);
wherein,
xvals contains:
0 = "A"
1 = "B"
2 = "C"
3 = "D"
4 = "E"
5 = "entry0"
6 = "entry1"
7 = "entry2"
8 = "entry3"
9 = "entry4"
and, ds1 contains:
0 = {Entry#4129} "Entry, xIndex: 0 val (sum): 0.0"
1 = {Entry#4130} "Entry, xIndex: 1 val (sum): 7400.0"
2 = {Entry#4131} "Entry, xIndex: 2 val (sum): 20634.4"
3 = {Entry#4132} "Entry, xIndex: 3 val (sum): 0.0"
4 = {Entry#4133} "Entry, xIndex: 4 val (sum): 60203.52"

I recommend that you simply write your own logic that excludes zero values from being added to the dataset.

Related

Polars Dataframe: Apply MinMaxScaler to a column with condition

I am trying to perform the following operation in Polars.
For value in column B which is below 80 will be scaled between 1 and 4, where as for anything above 80, will be set as 5.
df_pandas = pd.DataFrame(
{
"A": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
"B": [50, 300, 80, 12, 105, 78, 66, 42, 61.5, 35],
}
)
test_scaler = MinMaxScaler(feature_range=(1,4)) # from sklearn.preprocessing
df_pandas.loc[df_pandas['B']<80, 'Test'] = test_scaler.fit_transform(df_pandas.loc[df_pandas['B']<80, "B"].values.reshape(-1,1))
df_pandas = df_pandas.fillna(5)
This is what I did with Polars:
# dt is a dictionary
dt = df.filter(
pl.col('B')<80
).to_dict(as_series=False)
below_80 = list(dt.keys())
dt_scale = list(
test_scaler.fit_transform(
np.array(dt['B']).reshape(-1,1)
).reshape(-1) # reshape back to one dimensional
)
# reassign to dictionary dt
dt['B'] = dt_scale
dt_scale_df = pl.DataFrame(dt)
dt_scale_df
dummy = df.join(
dt_scale_df, how="left", on="A"
).fill_null(5)
dummy = dummy.rename({"B_right": "Test"})
Result:
A
B
Test
1
50.0
2.727273
2
300.0
5.000000
3
80.0
5.000000
4
12.0
1.000000
5
105.0
5.000000
6
78.0
4.000000
7
66.0
3.454545
8
42.0
2.363636
9
61.5
3.250000
10
35.0
2.045455
Is there a better approach for this?
Alright, I have got 3 examples for you that should help you from which the last should be preferred.
Because you only want to apply your scaler to a part of a column, we should ensure we only send that part of the data to the scaler. This can be done by:
window function over a partition
partition_by
when -> then -> otherwise + min_max expression
Window function over partititon
This requires a python function that will be applied over the partitions. In the function itself we then have to check in which partition we are and deal with it accordingly.
df = pl.from_pandas(df_pandas)
min_max_sc = MinMaxScaler((1, 4))
def my_scaler(s: pl.Series) -> pl.Series:
if s.len() > 0 and s[0] > 80:
out = (s * 0 + 5)
else:
out = pl.Series(min_max_sc.fit_transform(s.to_numpy().reshape(-1, 1)).flatten())
# ensure all types are the same
return out.cast(pl.Float64)
df.with_column(
pl.col("B").apply(my_scaler).over(pl.col("B") < 80).alias("Test")
)
partition_by
This partitions the the original dataframe to a dictionary holding the different partitions. We then only modify the partitions as needed.
parts = (df
.with_column((pl.col("B") < 80).alias("part"))
.partition_by("part", as_dict=True)
)
parts[True] = parts[True].with_column(
pl.col("B").map(
lambda s: pl.Series(min_max_sc.fit_transform(s.to_numpy().reshape(-1, 1)).flatten())
).alias("Test")
)
parts[False] = parts[False].with_column(
pl.lit(5.0).alias("Test")
)
pl.concat([df for df in parts.values()]).select(pl.all().exclude("part"))
when -> then -> otherwise + min_max expression
This one I like best. We can make function that creates a polars expression that is the min_max scaling function you need. This will have best performance.
def min_max_scaler(col: str, predicate: pl.Expr):
x = pl.col(col)
x_min = x.filter(predicate).min()
x_max = x.filter(predicate).max()
# * 3 + 1 to set scale between 1 - 4
return (x - x_min) / (x_max - x_min) * 3 + 1
predicate = pl.col("B") < 80
df.with_column(
pl.when(predicate)
.then(min_max_scaler("B", predicate))
.otherwise(5).alias("Test")
)

Random selection of a member's location in a nested cell of cells: Matlab

I have a nested cell of cells like the one below:
CellArray={1,1,1,{1,1,1,{1,1,{1,{1 1 1 1 1 1 1 1}, 1,1},1,1},1,1,1},1,1,1,{1,1,1,1}};
I need to randomly pick a location in CellArray. All members' locations of CellArray must have same chances to be chosen in the random selection process. Thanks.
You can capture the output of the celldisp function. Then use regex to extrcat indices:
s=evalc('celldisp(CellArray,'''')');
m = regexp(s, '\{[^\=]*\}', 'match');
Thanks to #excaza that suggested a clearer use of regexp
Result:
m =
{
[1,1] = {1}
[1,2] = {2}
[1,3] = {3}
[1,4] = {4}{1}
[1,5] = {4}{2}
[1,6] = {4}{3}
[1,7] = {4}{4}{1}
[1,8] = {4}{4}{2}
[1,9] = {4}{4}{3}{1}
[1,10] = {4}{4}{3}{2}{1}
[1,11] = {4}{4}{3}{2}{2}
[1,12] = {4}{4}{3}{2}{3}
[1,13] = {4}{4}{3}{2}{4}
[1,14] = {4}{4}{3}{2}{5}
[1,15] = {4}{4}{3}{2}{6}
[1,16] = {4}{4}{3}{2}{7}
[1,17] = {4}{4}{3}{2}{8}
[1,18] = {4}{4}{3}{3}
[1,19] = {4}{4}{3}{4}
[1,20] = {4}{4}{4}
[1,21] = {4}{4}{5}
[1,22] = {4}{5}
[1,23] = {4}{6}
[1,24] = {4}{7}
[1,25] = {5}
[1,26] = {6}
[1,27] = {7}
[1,28] = {8}{1}
[1,29] = {8}{2}
[1,30] = {8}{3}
[1,31] = {8}{4}
}
Use randi to select an index:
m{randi(numel(m))}

Can't assign a big number to a variable out of the while loop in scala

I want to write a program that can find the N-th number,which only contains factor 2 , 3 or 5.
def method3(n:Int):Int = {
var q2 = mutable.Queue[Int](2)
var q3 = mutable.Queue[Int](3)
var q5 = mutable.Queue[Int](5)
var count = 1
var x:Int = 0
while(count != n){
val minVal = Seq(q2,q3,q5).map(_.head).min
if(minVal == q2.head){
x = q2.dequeue()
q2.enqueue(2*x)
q3.enqueue(3*x)
q5.enqueue(5*x)
}else if(minVal == q3.head){
x = q3.dequeue()
q3.enqueue(3*x)
q5.enqueue(5*x)
}else{
x = q5.dequeue()
q5.enqueue(5*x)
}
count+=1
}
return x
}
println(method3(1000))
println(method3(10000))
println(method3(100000))
The results
51200000
0
0
When the input number gets larger , I get 0 from the function.
But if I change the function to
def method3(n:Int):Int = {
...
q5.enqueue(5*x)
}
if(x > 1000000000) println(('-',x)) //note here!!!
count+=1
}
return x
}
The results
51200000
(-,1006632960)
(-,1007769600)
(-,1012500000)
(-,1019215872)
(-,1020366720)
(-,1024000000)
(-,1025156250)
(-,1033121304)
(-,1036800000)
(-,1048576000)
(-,1049760000)
(-,1054687500)
(-,1061683200)
(-,1062882000)
(-,1073741824)
0
.....
So I don't know why the result equals to 0 when the input number grows larger.
An Int is only 32 bits (4 bytes). You're hitting the limits of what an Int can hold.
Take that last number you encounter: 1073741824. Multiply that by 2 and the result is negative (-2147483648). Multiply it by 4 and the result is zero.
BTW, if you're working with numbers "which only contains factor 2, 3 or 5", in other words the numbers 2, 3, 4, 5, 6, 8, 9, 10, 12, 14, 15, ... etc., then the 1,000th number in that sequence shouldn't be that big. By my calculations the result should only be 1365.

Creating an array of a specific size from data in an array of a larger size - averages

I want to find the average value across an array between the element(x) and element(x+1)
for val = 1: xMid_p-1
eapDia_p = diaArray_p(1,val);
baseDia_p = diaArray_p(1,end);
curDiaArray_p = linspace(eapDia_p, baseDia_p, xMid_p-1);
curRadArray_p = curDiaArray_p/2;
maxRad = max(curRadArray_p);
for val = 1 : xMid_p-1
ln(1,val) = maxRad(:) - curRadArray_p(val);
lnE(1,val) = ln(1,val).^3;
presAn(1,val)= acos(((refDia_p/2)*cos(refPresAng_p))./curRadArray_p(val));
arcToo(1,val) = 2 * curRadArray_p(val)*((twRefDia_p/refDia_p)+(tan(refPresAng_p)-refPresAng_p)-(tan(presAn(1,val))-presAn(1,val)));
chor(1,val) = 2 * curRadArray_p(val) * sin(arcToo(1,val)/(curRadArray_p(1,val)*2));
for val = 1 : xMid_p - 2
lnM(1,val) = maxRad(:) - curRadArray_p(val);
lnME(1,val)=lnM(1,val).^3;
end
end
lnCubed(1,:) = ln.^3;
lnMCubed(1,:) = lnM.^3;
lnEq = lnCubed(2:end) - lnMCubed;
end
please see chor(1,val), this would give the value :
chor =
1 2 3 4 5 6 7 8
I want to find the average chor, therefore the array will be one element smaller in size and will give the result
aveChor =
1.5 2.5 3.5 4.5 5.5 6.5 7.5
One approach using indexing -
aveChor = (chor(2:end) + [chor(1:end-1)])/2
Another approach using diff -
aveChor = (2*chor(1:end-1) + diff(chor))/2

Matlab - preprocess CSV file

I have a CSV file in a format similar to the following one:
title1
index columnA1 columnA2 columnA3
1 2 3 6
2 23 23 1
3 2 3 45
4 2 2 101
title2
index columnB1 columnB2 columnB3
1 23 53 6
2 22 13 1
3 5 4 43
4 8 6 102
I want to build a function readCustomCSV which receives a CSV file in the bellow illustrated format and a row index i and returns an output file with (for let's say i = 3) the following content:
title1
index columnA1 columnA2 columnA3
3 2 3 45
title2
index columnB1 columnB2 columnB3
3 5 4 43
Do you know how to use the csvread function in order to obtain this type of functionality?
It confuses me that there are 2 types sections. I was thinking at using the whole thing as a string and then split it into 2 .csv files and then read the corresponding line line.
try using this function :
I assumed that all tables have equal number of columns/rows. The code can definitely be shortened / improved / extended ;)
function multi_table_csvread (row_index)
filename_INPUT = 'multi_table.csv' ;
filename_OUTPUT = 'selected_row.csv' ;
fIN = fopen(filename_INPUT,'r');
nextLine = fgetl(fIN);
tableIndex = 0;
tableLine = 0;
csvTable = [];
% start reading the csv file, line by line
while nextLine ~= -1
lineStr = strtrim(strsplit(nextLine,',')) ;
% remove empty cells
lineStr(cellfun('isempty',lineStr)) = [] ;
tableLine = tableLine + 1 ;
% if 1 element start new table
if numel(lineStr) == 1
tableIndex = tableIndex + 1;
tableLine = 1;
csvTable{tableIndex,tableLine} = lineStr ;
else
lineStr = add_comas(lineStr) ;
csvTable{tableIndex,tableLine} = lineStr ;
end
nextLine = fgetl(fIN);
end
fclose(fIN);
fOUT = fopen(filename_OUTPUT,'w');
if row_index > size(csvTable,2) -2
error('The row index exceeds the maximum number of rows!')
end
for k = 1 : size(csvTable,1)
title = csvTable{k,1};
columnHeaders = csvTable{k,2};
selected_row = csvTable{k,row_index+2};
fprintf(fOUT,'%s\n',title{:});
fprintf(fOUT,'%s',columnHeaders{:});
fprintf(fOUT,'\n');
fprintf(fOUT,'%s',selected_row{:});
fprintf(fOUT,'\n');
end
fclose(fOUT);
function line_with_comas = add_comas(this_line)
for ii = 1 : length(this_line)-1
this_line{ii} = strcat(this_line{ii},',') ;
end
line_with_comas = this_line ;