0

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!

MyTivoli
  • 125
  • 2
  • 11

6 Answers6

1

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")
Ved Rathi
  • 327
  • 1
  • 12
0

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

Most Wanted
  • 6,254
  • 5
  • 53
  • 70
0

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
jupiterbjy
  • 2,882
  • 1
  • 10
  • 28
0

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

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 
Zoe
  • 27,060
  • 21
  • 118
  • 148
Matt
  • 225
  • 2
  • 9
0

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. ]
Michael Szczesny
  • 4,911
  • 5
  • 15
  • 32
  • Hello! Thanks for the answer! However, should 1.4 and 1.5 also appear in the missing values, I tested the solution, and not all missing values appear – MyTivoli Sep 25 '20 at 06:57
  • No, only one missing value in a sequence should be found – Michael Szczesny Sep 25 '20 at 08:04
  • I added a more general solution, where you can give an argument for the gap size. Please test this solution before using it in production. The handling of float values is error-prone because of the floating point error representation. – Michael Szczesny Sep 25 '20 at 09:01