I encountered this problem in the matplotlib xticklabels Text attribute. The minus signs for negative numbers are encoded as a "minus":
[โ] is a minus (Unicode 2212).
Minus: [&minus]; a.k.a. [−]; a.k.a. [−];
https://en.wikipedia.org/wiki/Wikipedia:Hyphens_and_dashes
Python seems to code minuses as 'hyphen-minus', Unicode 002D:
[-] is a hyphen-minus (ASCII keyboard, Unicode 002D)
Hyphen minus: [-]; a.k.a. [-];
Here is an example:
>> import matplotlib.pyplot as plt
>> import re
>> x = [0,1,2,3,4,5]
>> y = [0,1,2,1,2,1]
>> fig,ax = plt.subplots(1)
>> plt.plot(x,y)
.
If we try to get at the xticklabels, if we want to manually edit them, we use:
>> l = ax.get_xticklabels()
>> ticks = [i.get_text() for i in l]
>> print(ticks)
['โ1', '0', '1', '2', '3', '4', '5', '6']
>> ord(ticks[0])
8722
Try to convert it to an integer:
>> l = ax.get_xticklabels()
>> ticks = [int(i.get_text()) for i in l]
ValueError: invalid literal for int() with base 10: 'โ1'
This is the same error as in the question, which was difficult for others to recreate. To fix it, use regular expressions:
ticks = [int(re.sub(u"\u2212", "-", i.get_text())) for i in l]
print(ticks)
print(ticks[0] - 1)
[-1, 0, 1, 2, 3, 4, 5, 6]
-2
>> ord(ticks[0])
45
Answer from AhabTheArab on Stack OverflowI encountered this problem in the matplotlib xticklabels Text attribute. The minus signs for negative numbers are encoded as a "minus":
[โ] is a minus (Unicode 2212).
Minus: [&minus]; a.k.a. [−]; a.k.a. [−];
https://en.wikipedia.org/wiki/Wikipedia:Hyphens_and_dashes
Python seems to code minuses as 'hyphen-minus', Unicode 002D:
[-] is a hyphen-minus (ASCII keyboard, Unicode 002D)
Hyphen minus: [-]; a.k.a. [-];
Here is an example:
>> import matplotlib.pyplot as plt
>> import re
>> x = [0,1,2,3,4,5]
>> y = [0,1,2,1,2,1]
>> fig,ax = plt.subplots(1)
>> plt.plot(x,y)
.
If we try to get at the xticklabels, if we want to manually edit them, we use:
>> l = ax.get_xticklabels()
>> ticks = [i.get_text() for i in l]
>> print(ticks)
['โ1', '0', '1', '2', '3', '4', '5', '6']
>> ord(ticks[0])
8722
Try to convert it to an integer:
>> l = ax.get_xticklabels()
>> ticks = [int(i.get_text()) for i in l]
ValueError: invalid literal for int() with base 10: 'โ1'
This is the same error as in the question, which was difficult for others to recreate. To fix it, use regular expressions:
ticks = [int(re.sub(u"\u2212", "-", i.get_text())) for i in l]
print(ticks)
print(ticks[0] - 1)
[-1, 0, 1, 2, 3, 4, 5, 6]
-2
>> ord(ticks[0])
45
Actually, I cannot reproduce your error , it just work in python 2.7.13
>>>int("-5")
>>> -5
and in python 3.4
so, it could be a python version problem , I recommend updating your python version , by reinstalling the newer , from the site , it will replace it perfectly ( packages untouched ) , unless you are using , a special distribution like anaconda ..
for processing your list ( mixed chars and numbers ) use:
try: except:
statement.
You can easily remove the characters from the left first, like so:
choice.lstrip('-+').isdigit()
However it would probably be better to handle exceptions from invalid input instead:
print x
while True:
choice = raw_input("> ")
try:
y = int(choice)
break
except ValueError:
print "Invalid input."
x += y
Instead of checking if you can convert the input to a number you can just try the conversion and do something else if it fails:
choice = raw_input("> ")
try:
y = int(choice)
x += y
except ValueError:
print "Invalid input."
python - When using negative numbers to slice a string, why is 0 is disabled? - Stack Overflow
Handling negative number inputs from the user
Python string formatting: padding negative numbers - Stack Overflow
Python, negative numbers string to float - Stack Overflow
Use lstrip:
question.lstrip("-").isdigit()
Example:
>>>'-6'.lstrip('-')
'6'
>>>'-6'.lstrip('-').isdigit()
True
You can lstrip('+-') if you want to consider +6 a valid digit.
But I wouldn't use isdigit, you can try int(question), it'll throw an exception if the value cannot be represented as int:
try:
int(question)
except ValueError:
# not int
Use a try/except, if we cannot cast to an int it will set is_dig to False:
try:
int(question)
is_dig = True
except ValueError:
is_dig = False
if is_dig:
......
Or make a function:
def is_digit(n):
try:
int(n)
return True
except ValueError:
return False
if is_digit(question):
....
Looking at your edit cast to int at the start,checking if the input is a digit and then casting is pointless, do it in one step:
while a < 10:
try:
question = int(input("What is {} {} {} ?".format(n1,op,n2)))
except ValueError:
print("Invalid input")
continue # if we are here we ask user for input again
ans = opsop
n1 = random.randint(1,9)
n2 = random.randint(1,9)
op = random.choice(list(ops))
if question == ans:
print ("Well done")
else:
print("Wrong answer")
a += 1
Not sure what Z is doing at all but Z = Z + 0 is the same as not doing anything to Z at all 1 + 0 == 1
Using a function to take the input we can just use range:
def is_digit(n1,op,n2):
while True:
try:
n = int(input("What is {} {} {} ?".format(n1,op,n2)))
return n
except ValueError:
print("Invalid input")
for _ in range(a):
question = is_digit(n1,op,n2) # will only return a value when we get legal input
ans = opsop
n1 = random.randint(1,9)
n2 = random.randint(1,9)
op = random.choice(list(ops))
if question == ans:
print ("Well done")
else:
print("Wrong answer")
0 is the start of the sequence. Always, unambiguously. Changing its meaning to sometimes be the end would lead to a lot of confusion, especially when using variables for those two values.
Using negative indices is also not a different mode; negative indices are converted to positive indices relative to the length. Changing what element 0 refers to because the other slice input (start or stop) was a negative number makes no sense.
Because 0 always means the first element of the sequence, and there is no spelling for a negative zero, you cannot use 0 to mean the end of the sequence.
You can use None as the stop element to mean this instead, if you need to parameterise your indices:
start = -3
stop = None
result = a[start:stop]
You can also create a slice() object; the same rules apply for how indices are interpreted:
indices = slice(-3, None)
result = a[indices]
In fact, the interpreter translates the slice notation into a slice() object, which is then passed to the object to distinguish from straight-up indexing with a single integer; the a[start:stop] notation translates to type(a).__getitem__(a, slice(start, stop)) whereas a[42] becomes type(a).__getitem__(a, 42).
So by using a slice() object you can record either slicing or single-element indexing with a single variable.
It is boring to use negative slice in a loop if there is some chance to slice to 'negative zero', because [:-0] is not interpreted as expected.
But there is a simple way to solve the problem, just convert negative index to positive index by adding the length of the container.
E.g. Negative Slice Loop:
a = np.arange(10)
for i in range(5):
print(a[5-i:-i])
Answer:
[]
[4 5 6 7 8]
[3 4 5 6 7]
[2 3 4 5 6]
[1 2 3 4 5]
Convert to positive by adding the lenght:
for i in range(5):
print(a[5-i:len(a)-i])
Get the right answer:
[5 6 7 8 9]
[4 5 6 7 8]
[3 4 5 6 7]
[2 3 4 5 6]
[1 2 3 4 5]
This is a solution post. I had a problem and none of the solutions I found online were right for me. I eventually figured it out, and so I'm putting my solution here for future learners. Also if my solution is bad, I'll get some feedback. If you think it's obvious, then you're very clever, but no need to go to the trouble of letting me know!
I'm making an arithmetic game for my little one. So it had a line:
answer = int(input(f"What is {a} + {b}?"))
but of course he accidentally typed a letter and crashed the program. I wanted to handle this eventuality so I changed it to:
answer = input(f"What is {a} + {b}")
if answer.isnumeric():
answer = int(answer)
else:
print("That's not a number")
continue
the trouble is I also have subtraction questions and negative numbers! But "-1".isnumeric()==False !!
So I started googling: "isnumeric negative numbers" and "parsing negative numbers" and so on. The solutions I found were quite convoluted, mostly they seemed to be worrying about SQL injection and used concepts I hadn't learned yet. I wanted a solution that only used the beginner stuff I already knew. I realised that I only had to check if the first symbol is "-" and the rest is numeric. So:
if answer.isnumeric() or answer[0]=="-" and answer[1:].isnumeric():
is the solution!
EDIT: There was a typo in my solution, I meant to check if everything after the initial "-" is numeric. Otherwise an answer like "-3e" gets through. Thanks to u/Rizzityrekt28 for the catch
According to here, you need a space before the type descriptor, so both
'% d'%(1)
and
'{: d}'.format(1)
result in (notice the space)
' 1'
aligning nicely with the result of the above called with -1:
'-1'
you could use str.format, but adding 1 to the size to take the negative number into account here:
l = [1,-1,10,-10,4]
new_l = ["{1:0{0}d}".format(2 if x>=0 else 3,x) for x in l]
print(new_l)
result:
['01', '-01', '10', '-10', '04']
it works because format accepts nested expressions: you can pass the size ({:02d} or {:03d}) as a format item too when saves the hassle of formatting the format string in a first pass.
Make your reading a bit shorter:
verts = []
for line in f:
if line.startswith('v '):
verts.append([float(val) for val in line.split()[1:]])
This should replace your full for line in f: loop.
Make sure there is no other line later starting with v in your file. Maybe there is an empty line after the values, so you can stop reading there.
Now verts looks like this:
[[-543.243, -494.262, 1282.0],
[-538.79, -494.262, 1282.0],
[-536.422, -496.19, 1287.0],
[-531.951, -496.19, 1287.0],
[-527.481, -496.19, 1287.0],
[-213.909, -223.999, 581.0],
[-212.255, -224.384, 582.0],
[-209.15, -223.228, 579.0],
[-207.855, -223.999, 581.0],
[-205.482, -223.613, 580.0],
[-203.468, -223.613, 580.0],
[-201.106, -223.228, 579.0],
[-199.439, -223.613, 580.0],
[-197.765, -223.999, 581.0],
[-195.41, -223.613, 580.0],
[-193.062, -223.228, 579.0],
[-190.721, -222.842, 578.0],
[-189.04, -223.228, 579.0],
[-187.998, -224.384, 582.0],
[-185.976, -224.384, 582.0],
[-183.955, -224.384, 582.0],
[-181.621, -223.999, 581.0],
[-179.293, -223.613, 580.0],
[-177.279, -223.613, 580.0],
[-175.264, -223.613, 580.0],
[-173.549, -223.999, 581.0],
[-171.531, -223.999, 581.0],
[-169.513, -223.999, 581.0],
[-167.495, -223.999, 581.0],
[-165.761, -224.384, 582.0],
[-163.74, -224.384, 582.0],
[-161.718, -224.384, 582.0],
[-159.697, -224.384, 582.0],
[-157.946, -224.77, 583.0],
[-155.921, -224.77, 583.0],
[-153.896, -224.77, 583.0],
[-151.871, -224.77, 583.0],
[-149.847, -224.77, 583.0],
[-147.568, -224.384, 582.0]]
There's no problem converting to float a string of a negative number
>>> float('-5.6')
-5.6
>>> float('-531')
-531.0
Here's an example to parse a single line
>>> line = 'v -543.243 -494.262 1282'
>>> line.split()
['v', '-543.243', '-494.262', '1282']
>>> v, x, y, z = line.split()
>>> x
'-543.243'
>>> y
'-494.262'
>>> z
'1282'
Now we convert:
>>> x = float(x)
>>> x
-543.243
Hello, I'm trying to convert the values of a whole column in pandas that contains string numbers to float, but I have problems in converting negative numbers like the following:
ValueError: could not convert string to float: '-39686.9720.0170'
I tried:
df['OPENING_BALANCE'] = [x.replace('\U00002013', '-') for x in df["OPENING_BALANCE"]]but it doesn't work either, any help? :(
The simple solution is to user .replace('-9.0','0.1') (see documentation for .replace()), but I think you need more flexible solution based on regular expressions:
import re
new_string = re.sub(r'-\d+\.\d+', '0.1', your_string)
Looks like you are working with LAS files. You can check out libLAS to see if it works for you. And here is a tutorial.
The recommended way would be to try it:
try:
x = int(x)
except ValueError:
print "{} is not an integer".format(x)
If you also expect decimal numbers, use float() instead of int().
There might be a more elegant Python way, but a general method is to check if the first character is '-', and if so, call isdigit on the 2nd character onward.
Here's how I will handle it. The answer was already provided by @Fuledbyramen.
x = -3987
#arr = [-3,9,8,7]
if x < 0:
arr = [int(i) for i in str(x)[1:]]
arr[0] *= -1
else:
arr = [int(i) for i in str(x)]
print (arr)
The output of this will be:
[-3,9,8,7]
If value of x was 3987
x = 3987
then the output will be:
[3,9,8,7]
List comprehension works here
x = -3987
xs = str(x)
lst = [int(d) for d in (([xs[:2]]+list(xs[2:])) if xs[0]=='-' else xs)]
print(lst)
Output
[-3, 9, 8, 7]