Cannot use MatrixOp replace

Hi, I am trying to replace each timesort entry with another numeric value, I first tried to write a procedure using switch-case, but it doesn't work. I first thought this might be due to my bad use of the switch statement, then I tried using matrixop replace to replace the values in the wave attached.

However, what rings alert is that the command "MatrixOp newwave = replace (timesort, 0.03, 2700)" did nothing on the wave, but if I manually erase the original data point and type in 0.03 in the cell, the matrixop would work, but only on those points that I have just manually typed in.

Is there anything that gets funky of my wave? I tried "browse wave", it looks similar to the other waves.

Thanks to whomever that offers help!

Timesort.ibw (29.06 KB)
That's because the values in your wave aren't actually 0.03 (except for the ones you manually typed in).

You can see this by showing the wave in a table. Right click on the wave in the table, choose digits, and choose 16. Notice that what had previously displayed as "0.03" now displays as "0.02999999999997272".

Alternately, you cold use print/D to display a value from the wave:
print/D Timesort[9]
  0.0299999999999727
aclight wrote:
That's because the values in your wave aren't actually 0.03 (except for the ones you manually typed in).

You can see this by showing the wave in a table. Right click on the wave in the table, choose digits, and choose 16. Notice that what had previously displayed as "0.03" now displays as "0.02999999999997272".

Alternately, you cold use print/D to display a value from the wave:
print/D Timesort[9]
  0.0299999999999727



Ah, no wonder I cannot do the thing I want, this is the reason why. Thank you aclight!! What makes me puzzled is why it has to be >= 13 digits to be able to see the difference? It looks deceptive if not going that high in digits. How does Igor display the values stored in a wave? Also what would be a good way to truncate a number to keep only the decimal part and round to only 2 or 3 decimal places?

Thank you!
aclight wrote:
I don't know where your data came from, but you're probably a victim of floating point error (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html).

To round your data, you could use:
MatrixOp aa = round(TimeSort * 1000)/1000


Substitute different values for 1000 to change the precision of the rounding.

Thank you aclight! I think you are right in that I might be a victim in the floating point error. The funky data is after I use
Timesort = mod(Timesort, 1)

on the Timesort wave. What I am trying to do is chop the integer and only keep the digits after the decimal point in the new wave that is attached (this wave_decimal_day looks to be a normal wave).
I also tried
wave_decimal_day = wave_decimal_day - floor(wave_decimal_day)

which gave me the same problematic wave.

Assuming the wave with the floating point error is wave_pro,
I can use
MatrixOp aa = round(wave_pro*1000)/1000

as you have suggested to round to only two decimal points,
or
wave_pro = round(wave_pro*1000)/1000

It seems both can do the job, then my question would be if there is an advantage using one over the other? Or they are essentially doing the same thing?

I came up with
function chop1(todo)
     
    wave todo
     
    variable i
    string a
   
    for (i=0;i<numpnts(todo);i+=1)
             
        sprintf a, "%.2g\r", todo[i]
        todo[i] = str2num(a)
   
    endfor
   
end

to round, but it is extremely slow compared to if a new wave is created,
function chop2(todo)
     
    wave todo
     
    variable i
    string a
   
    duplicate/o todo newwave
    newwave = nan
   
     
    for (i=0;i<numpnts(newwave);i+=1)
           
        sprintf a, "%.2g\r", todo[i]
        newwave[i] = str2num(a)
   
    endfor
   
end

Is there a glitch if I treat the wave_pro using the two chop function? And what would be the reason for the slowness?

What I ultimately want to do with the wave_decimal_day is to replace all the points ending in the same decimal parts with a same data entry in time, so I tried
constant cons1 = 0.03, cons2 = 0.07, cons3 = 0.11, cons4 = 0.16, cons5 = 0.2
constant cons6 = 0.24, cons7 = 0.28, cons8 = 0.32, cons9= 0.36, cons10 = 0.41
constant cons11 = 0.45, cons12 = 0.49, cons13 = 0.53, cons14 =0.57, cons15 = 0.61
constant cons16 = 0.66, cons17 =0.7, cons18 = 0.74, cons19 = 0.78 ,cons20 = 0.82
constant cons21 = 0.86, cons22 = 0.91, cons23=95,cons24=0.99

function numericswitch(a)
    variable a

    variable c
 
    switch(a)
       
        case cons1 :   
            c=2700     
                               
            break
               
        case cons2:
            c= 6300
               
            break
   
               
        case cons3:
            c= 9900
            break
   
        case cons4:
            c= 13500
            break
       
        case cons5:
            c=17100
            break
       
        case cons6:
            c= 20700
            break
       
        case cons7:
            c=24300
            break
     
        case cons8:
            c= 27900
            break
     
        case cons9:
            c=31500
            break
     
        case cons10:
            c=35100
            break
       
        case cons11:
            c= 38700
            break
     
        case cons12:
            c= 42300
            break
       
        case cons13:
            c= 45900
            break
       
        case cons14:
            c= 49500
            break
       
        case cons15:
            c= 53100
            break
       
        case cons16:
            c= 56700
            break
                     
        case cons17:
            c= 60300
            break
                       
        case cons18:
            c=63900
            break
                       
        case cons19:
            c= 67500
            break
                       
        case cons20:
            c= 71100
            break
                       
        case cons21:
            c= 74700
            break
                     
        case cons22:
            c= 78300
            break
                     
        case cons23:
            c= 81900
            break
                     
        case cons24:
            c= 85500
            break
    endswitch
    return c          
end

and then loop through each point in the wave that has already been truncated to the two decimal points, but I can never get it right. What is it that I did wrong?

This ends up to be a bit too long, but thank you again in advance and indeed!
wave_decimal_day.ibw (18.64 KB)
mwpro wrote:
aclight wrote:
I don't know where your data came from, but you're probably a victim of floating point error (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html).

To round your data, you could use:
MatrixOp aa = round(TimeSort * 1000)/1000


Substitute different values for 1000 to change the precision of the rounding.

Thank you aclight! I think you are right in that I might be a victim in the floating point error. The funky data is after I use
Timesort = mod(Timesort, 1)

on the Timesort wave. What I am trying to do is chop the integer and only keep the digits after the decimal point in the new wave that is attached (this wave_decimal_day looks to be a normal wave).
I also tried
wave_decimal_day = wave_decimal_day - floor(wave_decimal_day)

which gave me the same problematic wave.

Assuming the wave with the floating point error is wave_pro,
I can use
MatrixOp aa = round(wave_pro*1000)/1000

as you have suggested to round to only two decimal points,
or
wave_pro = round(wave_pro*1000)/1000

It seems both can do the job, then my question would be if there is an advantage using one over the other? Or they are essentially doing the same thing?

I came up with
function chop1(todo)
     
    wave todo
     
    variable i
    string a
   
    for (i=0;i<numpnts(todo);i+=1)
             
        sprintf a, "%.2g\r", todo[i]
        todo[i] = str2num(a)
   
    endfor
   
end

to round, but it is extremely slow compared to if a new wave is created,
function chop2(todo)
     
    wave todo
     
    variable i
    string a
   
    duplicate/o todo newwave
    newwave = nan
   
     
    for (i=0;i<numpnts(newwave);i+=1)
           
        sprintf a, "%.2g\r", todo[i]
        newwave[i] = str2num(a)
   
    endfor
   
end

Is there a glitch if I treat the wave_pro using the two chop function? And what would be the reason for the slowness?


I'm not sure what you're asking.

Your two chop functions execute in about the same amount of time on my machine (a few ms difference).

In general, MatrixOp is much faster than a wave assignment statement which is much faster than a loop (such as your chop functions). There are exceptions to the rule depending on what exactly you are doing.


mwpro wrote:

What I ultimately want to do with the wave_decimal_day is to replace all the points ending in the same decimal parts with a same data entry in time, so I tried....


This might be what you're looking for:
MatrixOp/O bb = round((wave_decimal_day - floor(wave_decimal_day)) * 90000)

aclight wrote:
mwpro wrote:
aclight wrote:
I don't know where your data came from, but you're probably a victim of floating point error (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html).

To round your data, you could use:
MatrixOp aa = round(TimeSort * 1000)/1000


Substitute different values for 1000 to change the precision of the rounding.

Thank you aclight! I think you are right in that I might be a victim in the floating point error. The funky data is after I use
Timesort = mod(Timesort, 1)

on the Timesort wave. What I am trying to do is chop the integer and only keep the digits after the decimal point in the new wave that is attached (this wave_decimal_day looks to be a normal wave).
I also tried
wave_decimal_day = wave_decimal_day - floor(wave_decimal_day)

which gave me the same problematic wave.

Assuming the wave with the floating point error is wave_pro,
I can use
MatrixOp aa = round(wave_pro*1000)/1000

as you have suggested to round to only two decimal points,
or
wave_pro = round(wave_pro*1000)/1000

It seems both can do the job, then my question would be if there is an advantage using one over the other? Or they are essentially doing the same thing?

I came up with
function chop1(todo)
     
    wave todo
     
    variable i
    string a
   
    for (i=0;i<numpnts(todo);i+=1)
             
        sprintf a, "%.2g\r", todo[i]
        todo[i] = str2num(a)
   
    endfor
   
end

to round, but it is extremely slow compared to if a new wave is created,
function chop2(todo)
     
    wave todo
     
    variable i
    string a
   
    duplicate/o todo newwave
    newwave = nan
   
     
    for (i=0;i<numpnts(newwave);i+=1)
           
        sprintf a, "%.2g\r", todo[i]
        newwave[i] = str2num(a)
   
    endfor
   
end

Is there a glitch if I treat the wave_pro using the two chop function? And what would be the reason for the slowness?


I'm not sure what you're asking.

Your two chop functions execute in about the same amount of time on my machine (a few ms difference).

In general, MatrixOp is much faster than a wave assignment statement which is much faster than a loop (such as your chop functions). There are exceptions to the rule depending on what exactly you are doing.


mwpro wrote:

What I ultimately want to do with the wave_decimal_day is to replace all the points ending in the same decimal parts with a same data entry in time, so I tried....


This might be what you're looking for:
MatrixOp/O bb = round((wave_decimal_day - floor(wave_decimal_day)) * 90000)



That is an easy solve, thank you aclight! I was wondering if there is a procedure that functions like a pivot table in Igor? Thanks!