I've got a series of positive and negative numbers and want to increase the absolute value of every number by one, while still keeping them positive/negative.
0.2 -> 1.2
-0.3 -> -1.3
How can I do that?
Let us try sign from numpy
s=pd.Series([0.2,-0.3])
(s.abs()+1)*np.sign(s)
0 1.2
1 -1.3
dtype: float64
Or np.select
np.select([s>0,s<0],[s+1,s-1],default=1)
array([ 1.2, -1.3])
Also we can do np.where
np.where(s>=0,s+1,s-1)
You can do a np.where:
s += np.where(s>=0, 1, -1)
#YOBEN_S' answer sufficiently covers it within the pandas/numpy space - if you are working within lists, and outside Pandas/Numpy, the below code may suffice, as it uses the math module within python :
from math import fabs, copysign
[(fabs(ent)+1)*copysign(1,ent) for ent in l]
[1.2, -1.3]
Related
numpy.r_ can be use to build arrays quickly from slice notation. However, the following example appears to demonstrate inconsistent behavior:
>>> import numpy as np
>>> a = np.r_[0.1 : 0.3 : 0.1]
>>> a
array([0.1, 0.2])
Endpoint of the slice 0.3 not included - as expected.
>>> b = np.r_[0.1 : 0.4 : 0.1]
>>> b
array([0.1, 0.2, 0.3, 0.4])
Endpoint of the slice 0.4 included!
There does not appear to be an explanation for this behavior in the documentation.
When c is real, numpy.r_[a:b:c] is equivalent to numpy.arange(a, b, c). Using floats here is a bad idea, as documented in the numpy.arange docs - the length may be wrong, because a length calculation based on floating-point values is subject to floating-point rounding error, and the step itself may suffer precision loss due to implementation details of how NumPy handles the step internally.
As suggested in the numpy.arange docs, you should use numpy.linspace instead. numpy.linspace takes an element count as an integer, instead of taking a step:
b = numpy.linspace(0.1, 0.4, num=3, endpoint=False)
because in python real numbers are not always rounded, as in your example horizontal step 0.2+0.1 is close to 0.300000000000004 and the result will be wrong.
I would use this way but it seems to be more complicated:
from decimal import *
import numpy as np
getcontext().prec = 6 # setting new values for precision, rounding, or enabled traps
b = Decimal(2)/Decimal(5) # 0.4
a = Decimal(1)/Decimal(10) # 0.1
print(np.r_[a: b : a])
I have a pandas series
In [1]: import pandas as pd
In [2]: s = pd.Series([1.3, 2.6, 1.24, 1.27, 1.45])
and I need to round the numbers.
In [4]: s.round(1)
Out[4]:
0 1.3
1 2.6
2 1.2
3 1.3
4 1.4
dtype: float64
it works for 1.27, however 1.45 is rounded to be 1.4, is it the problem of the precision loss of float type? If it is, how can I deal with this problem?
This isn't a bug but it is because, most decimal numbers cannot be represented exactly as a float.
https://www.programiz.com/python-programming/methods/built-in/round
another way of rounding is:
int(number*10^precission+0.5)
however, you might run in simular problems because who knows if 1.45 is closer to 1.4499999.. or 1.4500...1
In general, round() often fails due to floats being imprecise estimates.
In this case though, it's because of a convention by which half of all the numbers (evens) are rounded down, in order to balance out rounding error.
You can pretty easily disable this behavior:
round(x[, n])
x rounded to n digits, rounding half to even. If n is omitted, it defaults to 0.
This question already has answers here:
Is floating point math broken?
(31 answers)
Closed 6 years ago.
I am new to python and I tried this:
import numpy as np
x = np.arange(0.7,1.3,0.1)
print (x)
y = np.arange(0.6,1.3,0.1)
print (y)
The output was [ 0.7 0.8 0.9 1. 1.1 1.2 1.3] and [ 0.6 0.7 0.8 0.9 1. 1.1 1.2]. Why in the first case 1.3 appears in the list and in the second case it doesn't?
This is due to rounding errors. If you actually print the last element in x in it's full precision, you'll see that it is smaller than 1.3:
>>> import numpy as np
>>> x = np.arange(0.7,1.3,0.1)
>>> 1.3 > x[-1]
True
>>> x[-1]
1.2999999999999998
Note, as stated in the documentation
When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases.:
arange is not suitable for floating point numbers:
When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases.
I'm not familiar with the internals of numpy, but my guess is that this is a side effect of floating point numbers not being exact (meaning that they can't exactly represent some values).
See the numpy.arange documentation here:
specifically "When using a non-integer step, such as 0.1, the results will often not be consistent. It is better to use linspace for these cases"
I am trying to write a programme in Python 3which calculates the mean of the absolute differences between successive values.
EDIT: As the code was removed from the question, updating answer, moving the issues with code to bottom.
As given in comments you can use enumerate() to get the index as well as element from the array and then use that to calculate the mean. Example -
>>> def absolute_difference(v):
... sum_diff = 0
... for i,x in enumerate(v):
... if i+1 < len(v):
... sum_diff += abs(v[i+1] - x)
... r = sum_diff/len(v)
... return r
...
>>> absolute_difference([4.0, 4.2, 4.1, 4.4, 4.3])
0.1400000000000004
Lots of issues in the code (that you seem to have removed) -
Why are you converting your absolute difference to float ? float mathematics is not accurate , as you can see from the sum of difference in your code - 0.20000000000000018 . In your case you do not need to convert them to float.
The main issue of 0.0 for r occurs because you are using // to divide, // truncates the division to the nearest integer, so diving 7.0 by something grater than that using // would always result in 0.0 . Example -
>>> 7.0 // 8.0
0.0
>>> 7.0/8.0
0.875
For your case, you should divide using / .
You are taking the mean in each iteration of the loop, though that is not an issue , it may not be completely needed. If you do not want to take the mean in each iteration of the loop, you should indent it outside the loop.
You are using // which means integer division in python 3
That is
i.e)
2/4 =0.5
2//4=0
Just replace the // with / when calculating r
Here is another approach:
def absolute_difference(values):
last = values[0]
total = 0
for value in values[1:]:
total += abs(value - last)
last = value
return total/(len(values)-1)
print('{:.5f}'.format(absolute_difference([4.0, 4.2, 4.1, 4.4, 4.3])))
Giving the answer: 0.17500
Also, to prevent None from appearing at the end, you must have return at the end of your definition. This happens if you make another variable "equal to" (=) your definition. This was shown in the other posts, but I'm stating this just to highlight things out.
I want to take a floating-point number and round it down to the nearest integer. However, if it's not a whole, I always want to round down the variable, regardless of how close it is to the next integer up. Is there a way to do this?
Simple
int(x)
will work as well.
One of these should work:
import math
math.trunc(1.5)
> 1
math.trunc(-1.5)
> -1
math.floor(1.5)
> 1
math.floor(-1.5)
> -2
x//1
The // operator returns the floor of the division. Since dividing by 1 doesn't change your number, this is equivalent to floor but no import is needed.
Notes:
This returns a float
This rounds towards -∞
To get floating point result simply use:
round(x-0.5)
It works for negative numbers as well.
I think you need a floor function :
math.floor(x)
a lot of people say to use int(x), and this works ok for most cases, but there is a little problem. If OP's result is:
x = 1.9999999999999999
it will round to
x = 2
after the 16th 9 it will round. This is not a big deal if you are sure you will never come across such thing. But it's something to keep in mind.
If you don't want to import math, you could use:
int(round(x))
Here's a piece of documentation:
>>> help(round)
Help on built-in function round in module __builtin__:
round(...)
round(number[, ndigits]) -> floating point number
Round a number to a given precision in decimal digits (default 0 digits).
This always returns a floating point number. Precision may be negative.
If you working with numpy, you can use the following solution which also works with negative numbers (it's also working on arrays)
import numpy as np
def round_down(num):
if num < 0:
return -np.ceil(abs(num))
else:
return np.int32(num)
round_down = np.vectorize(round_down)
round_down([-1.1, -1.5, -1.6, 0, 1.1, 1.5, 1.6])
> array([-2., -2., -2., 0., 1., 1., 1.])
I think it will also work if you just use the math module instead of numpy module.
Just make round(x-0.5) this will always return the next rounded down Integer value of your Float. You can also easily round up by do round(x+0.5)
Don't know if you solved this, but I just stumble upon this question. If you want to get rid of decimal points, you could use int(x) and it will eliminate all decimal digits. Theres no need to use round(x).
It may be very simple, but couldn't you just round it up then minus 1?
For example:
number=1.5
round(number)-1
> 1
I used this code where you subtract 0.5 from the number and when you round it, it is the original number rounded down.
round(a-0.5)