Dax - Reverse margin calculation on a slider slicer - powerbi

I have a measure that calculates the reverse margin following this principle:
RMS=C/(1−(MP/100))
Where RMS is the Reverse Margin Sell Price (£)
C is the cost of the product (£)
MP is the margin percentage (%)
The DAX measure itself looks like this:
_rms20% =
VAR newGP = DIVIDE([_cost], (1-20/100))
RETURN
IF([_%currentGP]>0.2, BLANK(), newGP)
So if the current GP percentage is higher than 20% blank space is returned, if it is lower I have the RMS calculation returned.
This works nicely but problem occurs when I create a "What-IF" parameter slider as follows:
Increase = GENERATESERIES(0, 100, 1)
Increase Value = SELECTEDVALUE('Increase'[Increase])
and use this parameter with the RMS measure:
_slider% = [_rms20%] * (100+'Increase'[Increase Value])/100
For example if my Cost is £27.26 and desired gp is 20% than cost has to be increased to £34.08 - this is done by the basic calculation following the principle mentioned above.
If I put this on a slider and increase it by 5 to 25% the value it shows is £35.78 while in fact it should be £36.34.
I have been trying to fix this for some time now so any advice/recommendation would be very appreciated.

Related

Power BI: how to remove top 20% of values from an average

I'm working with call center data and looking to calculate the average ring time of calls while removing the highest 20% of ring times. I assume I'll need to use PERCENTILEX.EXC embedded somewhere in AVERAGE, but I'm not quite sure where, or if I'm totally off base. 2 other caveats on this are that there are calls answered immediately (queue time = 0) which have to be counted in the average time and only data where the disposition column = Handled are used.
Example:
The Aborted and Abandoned call would be filtered out. Of the remaining calls, the top 20% of queue times (the 14,9, 6, and one of the 5s) would be eliminated and the average would be 3 seconds.
Appreciate any help on this!
I would do it like this:
VAR totalRows = COUNTROWS(FILTER(table, table[disposition] = "Handled"))
VAR bottomN = ROUNDDOWN(totalRows * .8, 0)
RETURN AVERAGEX(TOPN(bottomN, FILTER(table, table[disposition] = "Handled"), table[queue time], ASC),table[queue time])

Power BI - "Other" Classfication Based on Percentage of Total

quick question:
I have a total amount that is divided into several classifications, like so:
Total: 7bn
Classification 1: 3bn,
Classification 2: 1bn,
... ,
Classification N: 0,3M
N is such a big number that when I put in a graph, most of the classifications don't even show up in there, so my manager suggested that I took anything that represents less than 5% of the total 7bn and classified them as "Others" to put it all together in the visual.
Then I made a measure "% of total" like:
% of total =
divide(
sum(values),
sumx(
allselected(table),
values
)
)
And this actually works perfect, except...
I wanna make a measure (or calculated column) that returns something like:
new classification =
if(
[% of total] > 0.05,
"Others",
[classification]
)
just to classify for me in the graph
but then only one of the new classifications returns as the old one, the rest returns "Others", but I know there's more than one, according to [% of total].
Can you think of another way to make this work? Is this a dumb question?
Thanks in advance
Create 2 separate measure for [others] & [classification] and create your final measure as below-
new classification =
var is_greater = IF([% of total] > 0.05, 1, 0)
RETURN
SWITCH(
is_greater ,
1,[Others]",
[classification]
)

how to find time band using dax in power bi?

I would like to find time band of half hour.Suppose i have a time stamp :
2019-03-12 01:20:00 this exists between time band of 1:00-1:30, similarly
2019-03-12 04:33:00 this exists between time band of 4:30-5:00.
I have column of n number of timestamp.
Is there any dax function that i can write to find the time band or there is any other process?
Thanks in advance!!
Consider something like this:
TimeBand =
FORMAT(FLOOR(MyTable[Timestamp], 1/48),"h:mm")
& " - "
& FORMAT(CEILING(MyTable[Timestamp], 1/48),"h:mm")
Floor and Ceiling are very similar functions -- they essentially round to the nearest multiple. Floor picks the biggest multiple that is smaller, and ceiling picks the smallest multiple that is bigger. Usually we round to powers of 10, but with this function we can round to the nearest 5, or 7, or 1/3.
Combine this with the understanding that PowerBI values all datetimes as a special kind of number -- it is simply the count of days since 12/30/1899. (Try it, create a calculated column and set its value to 0, then display it as a date time). So in this system "1" is one day. That means 1/24 is one hour, and 1/24/60 is one minute. It follows, then, that 30/24/60 is 30 minutes, and that reduces to 1/48.
So now we can take Floor/Ceiling, give it a time, and have it round that datetime to the nearest half-hour -- either down or up depending on which function you choose.
Use format to convert everything to text, and you're all set.
Here's some sample data generated in Power Query:
let
Source = List.Generate(()=> #datetime(2020,3,1,0,0,0), each _ < #datetime(2020,3,1,0,0,0) + #duration(1,0,0,0) , each _ + #duration(0,0,5,0)),
#"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), {"Timestamp"}, null, ExtraValues.Error)
in
#"Converted to Table"
And the results of our DAX:
Hope it Helps!

Parseval's Theorem does not hold for FFT of a sinusoid + noise?

Thanks in advance for any help on this subject. I've recently been trying to work out Parseval's theorem for discrete fourier transforms when noise is included. I based my code from this code.
What I expected to see is that (as when no noise is included) the total power in the frequency domain is half that of the total power in the time-domain, as I have cut off the negative frequencies.
However, as more noise is added to the time-domain signal, the total power of the fourier transform of the signal+noise becomes much less than half of the total power of the signal+noise.
My code is as follows:
import numpy as np
import numpy.fft as nf
import matplotlib.pyplot as plt
def findingdifference(randomvalues):
n = int(1e7) #number of points
tmax = 40e-3 #measurement time
f1 = 30e6 #beat frequency
t = np.linspace(-tmax,tmax,num=n) #define time axis
dt = t[1]-t[0] #time spacing
gt = np.sin(2*np.pi*f1*t)+randomvalues #make a sin + noise
fftfreq = nf.fftfreq(n,dt) #defining frequency (x) axis
hkk = nf.fft(gt) # fourier transform of sinusoid + noise
hkn = nf.fft(randomvalues) #fourier transform of just noise
fftfreq = fftfreq[fftfreq>0] #only taking positive frequencies
hkk = hkk[fftfreq>0]
hkn = hkn[fftfreq>0]
timedomain_p = sum(abs(gt)**2.0)*dt #parseval's theorem for time
freqdomain_p = sum(abs(hkk)**2.0)*dt/n # parseval's therom for frequency
difference = (timedomain_p-freqdomain_p)/timedomain_p*100 #percentage diff
tdomain_pn = sum(abs(randomvalues)**2.0)*dt #parseval's for time
fdomain_pn = sum(abs(hkn)**2.0)*dt/n # parseval's for frequency
difference_n = (tdomain_pn-fdomain_pn)/tdomain_pn*100 #percent diff
return difference,difference_n
def definingvalues(max_amp,length):
noise_amplitude = np.linspace(0,max_amp,length) #defining noise amplitude
difference = np.zeros((2,len(noise_amplitude)))
randomvals = np.random.random(int(1e7)) #defining noise
for i in range(len(noise_amplitude)):
difference[:,i] = (findingdifference(noise_amplitude[i]*randomvals))
return noise_amplitude,difference
def figure(max_amp,length):
noise_amplitude,difference = definingvalues(max_amp,length)
plt.figure()
plt.plot(noise_amplitude,difference[0,:],color='red')
plt.plot(noise_amplitude,difference[1,:],color='blue')
plt.xlabel('Noise_Variable')
plt.ylabel(r'Difference in $\%$')
plt.show()
return
figure(max_amp=3,length=21)
My final graph looks like this figure. Am I doing something wrong when working this out? Is there an physical reason that this trend occurs with added noise? Is it to do with doing a fourier transform on a not perfectly sinusoidal signal? The reason I am doing this is to understand a very noisy sinusoidal signal that I have real data for.
Parseval's theorem holds in general if you use the whole spectrum (positive and negative) frequencies to compute the power.
The reason for the discrepancy is the DC (f=0) component, which is treated somewhat special.
First, where does the DC component come from? You use np.random.random to generate random values between 0 and 1. So on average you raise the signal by 0.5*noise_amplitude, which entails a lot of power. This power is correctly computed in the time domain.
However, in the frequency domain, there is only a single FFT bin that corresponds to f=0. The power of all other frequencies is distributed over two bins, only the DC power is contained in a single bin.
By scaling the noise you add DC power. By removing the negative frequencies you remove half the signal power, but most of the noise power is located in the DC component which is used fully.
You have several options:
Use all frequencies to compute the power.
Use noise without a DC component: randomvals = np.random.random(int(1e7)) - 0.5
"Fix" the power calculation by removing half of the DC power: hkk[fftfreq==0] /= np.sqrt(2)
I'd go with option 1. The second might be OK and I don't really recommend 3.
Finally, there is a minor problem with the code:
fftfreq = fftfreq[fftfreq>0] #only taking positive frequencies
hkk = hkk[fftfreq>0]
hkn = hkn[fftfreq>0]
This does not really make sense. Better change it to
hkk = hkk[fftfreq>=0]
hkn = hkn[fftfreq>=0]
or completely remove it for option 1.

How to to solve divide by zero error (NaN - Not a Number) in my formula in Power BI?

I have a column with a formula which reads:
Utilisation (Excl. Time-off) = Utilisation_Excl_Timeoff[Billable Hours]/(Utilisation_Excl_Timeoff[Available Hours] - Utilisation_Excl_Timeoff[Timeoff Hours (Excl. Public)])
It gives me a "NaN" error in my calculated column for some of the cells due to divide by zero.
I would like to replace the NaN with a 0% instead so that the column displays correctly in my matrix chart.
Take a look at the DIVIDE function (https://msdn.microsoft.com/en-us/library/jj677276.aspx).
This is a 'safe divide` function with the option to return an alternative value if the division returns an error.
-JP
If you are looking for solution in M, then add conditional column:
Set up Otherwise temporarily to dividend column, here I took [Value] column. After doing this change in editor [Value] to [Value]/[Units]. This returns null wherever Units is 0. You may change returned output to 0% according to thy wish.
Alternatively, you can do it as well by adding this step:
= Table.AddColumn(#"Previous Step", "UnitPrice", each if [Units] = 0 then "0%" else [Value]/[Units])
IFERROR(value, value_if_error) function can do this. MSDN
Utilisation (Excl. Time-off) = IFERROR(Utilisation_Excl_Timeoff[Billable Hours]/(Utilisation_Excl_Timeoff[Available Hours] - Utilisation_Excl_Timeoff[Timeoff Hours (Excl. Public)]), 0)