0
votes

I am trying to find "missing" values in a python array of floats.

Such that in this case [1.1, 1.3, 2.1, 2.2, 2.3] I would like to print "1.2"

I dont have much experience with floats, I have tried something like this How to find a missing number from a list? but it doesn't work on floats.

Thanks!

6
you have to be more specific because there is a lot of floats between two integers. - woblob
How do you know that 1.4 is not missing as well? Or that the difference should not actually be 0.2? And why is a value missing between 1.1 and 1.3, but not between 1.3 and 2.1? - tobias_k
What's the logical criteria you want to implement? - coelidonum
I don't.. I would like it to just look at the highest possible, so 1.3 and 2.3 in this case - MyTivoli
So all floats will have 1 digit after point? - GProst

6 Answers

1
votes

To solve this, the problem would need to be simplified first, I am assuming that all the values would be float and with one decimal place, also let's assume that there can be multiple ranges like 1.1-1.3 and 2.1-2.3, also assuming that the numbers are in sorted order, here is a solution. It is written in python 3 by the way

    vals = [1.1, 1.3, 2.1, 2.2, 2.3] # This will be the values in which to find the missing number

# The logic starts from here
for i in range(len(vals) - 1):
    if vals[i + 1] * 10 - vals[i] * 10 == 2:
        print((vals[i] * 10 + 1)/10)

print("\nfinished")
0
votes

You might want to use https://numpy.org/doc/stable/reference/generated/numpy.arange.html

and create a list of floats (if you know start, end, step values)

Then you can create two sets and use difference to find missing values

0
votes

Simplest yet dumb way:

  1. Split float to integer and decimal parts.
  2. Create cartesian product of both to generate Full array.
  3. Use set and XOR to find out missing ones.
from itertools import product


source = [1.1, 1.3, 2.1, 2.2, 2.3]
separated = [str(n).split(".") for n in source]

integers, decimals = map(set, zip(*separated))
products = [float(f"{i}.{d}") for i, d in product(integers, decimals)]

print(*(set(products) ^ set(source)))

output:

1.2
0
votes

I guess that the solutions to the problem you quote proprably work on your case, you just need to adapt the built-in range function to numpy.arange that allow you to create a range of numbers with floats.

it gets something like that: (just did a simple example)

import numpy as np

np_range = np.arange(1, 2, 0.1)
float_list = [1.2, 1.3, 1.4, 1.6]

for i in np_range:
    if not round(i, 1) in float_list:
        print(round(i, 1))

output:

 1.0
 1.1
 1.5
 1.7
 1.8
 1.9
0
votes

This is an absolutely AWFUL way to do this, but depending on how many numbers you have in the list and how difficult the other solutions are you might appreciate it.

If you write

firstvalue = 1.1
secondvalue = 1.2
thirdvalue = 1.3
#assign these for every value you are keeping track of
if firstvalue in val: #(or whatever you named your list)
    print("1.1 is in the list")
else:
    print("1.1 is missing!")
if secondvalue in val:
    print("1.2 is in the list")
else:
    print("1.2 is missing!")
#etc etc etc for every value in the list. It's tedious and dumb but if you have few enough values in your list it might be your simplest option 
0
votes

With numpy

import numpy as np
    
arr = [1.1, 1.3, 2.1, 2.2, 2.3]
find_gaps = np.array(arr).round(1)
find_gaps[np.r_[np.diff(find_gaps).round(1), False] == 0.2] + 0.1

Output

array([1.2])

Test with random data

import numpy as np
np.random.seed(10)

arr = np.arange(0.1, 10.4, 0.1)
mask = np.random.randint(0,2, len(arr)).astype(np.bool)
gaps = arr[mask]
print(gaps)

find_gaps = np.array(gaps).round(1)
print('missing values:')
print(find_gaps[np.r_[np.diff(find_gaps).round(1), False] == 0.2] + 0.1)

Output

[ 0.1  0.2  0.4  0.6  0.7  0.9  1.   1.2  1.3  1.6  2.2  2.5  2.6  2.9
  3.2  3.6  3.7  3.9  4.   4.1  4.2  4.3  4.5  5.   5.2  5.3  5.4  5.6
  5.8  5.9  6.1  6.4  6.8  6.9  7.3  7.5  7.6  7.8  7.9  8.1  8.7  8.9
  9.7  9.8 10.  10.1]
missing values:
[0.3 0.5 0.8 1.1 3.8 4.4 5.1 5.5 5.7 6.  7.4 7.7 8.  8.8 9.9]

More general solution

Find all missing value with specific gap size

import numpy as np

def find_missing(find_gaps, gaps = 1):
    find_gaps = np.array(find_gaps)
    gaps_diff = np.r_[np.diff(find_gaps).round(1), False]
    gaps_index = find_gaps[(gaps_diff >= 0.2) & (gaps_diff <= round(0.1*(gaps + 1),1))]
    gaps_values = np.searchsorted(find_gaps, gaps_index)
    ranges = np.vstack([(find_gaps[gaps_values]+0.1).round(1),find_gaps[gaps_values+1]]).T
    return np.concatenate([np.arange(start, end, 0.1001) for start, end in ranges]).round(1)

vals = [0.1,0.3, 0.6, 0.7, 1.1, 1.5, 1.8, 2.1]
print('Vals:', vals)
print('gap=1', find_missing(vals, gaps = 1))
print('gap=2', find_missing(vals, gaps = 2))
print('gap=3', find_missing(vals, gaps = 3))

Output

Vals: [0.1, 0.3, 0.6, 0.7, 1.1, 1.5, 1.8, 2.1]
gap=1 [0.2]
gap=2 [0.2 0.4 0.5 1.6 1.7 1.9 2. ]
gap=3 [0.2 0.4 0.5 0.8 0.9 1.  1.2 1.3 1.4 1.6 1.7 1.9 2. ]