首页 > 解决方案 > python3如何创建一个检查空值并取相邻值的平均值来替换空值的列表?

问题描述

我想创建一个提供输出的列表,如果原始列表有一个空值,它将取相邻值的总和平均值来替换它。假设缺失数据用 -99 表示

def clean_missing_data():
    
    data_list = []
    
    for number, adjacent in enumerate(a):
        
        if (number != -99):

            data_list.append(number)
            
        else:
            
            adjacent_left = a[number-1]
            adjacent_right = a[number+1]
            fill_in = (adjacent_left + adjacent_right) / 2    
            data_list.append(fill_in)
    
    return data_list

a = [1,2,3,-99,5]

check_data = clean_missing_data()

print('original test case:', a)
print('After clearing, the test case became:', check_data)

输出

original test case: [1, 2, 3, -99, 5]
After clearing, the test case became: [0, 1, 2, 3, 4]

例如对于这个测试用例,缺失值是列表的第四个数字(用-99表示),这意味着列表取相邻数据的总和平均值;值 3 和 5,并将其替换回列表。

本质上,它的意思是:[1,2,3, (3+5)/2, 5]

请帮忙!

标签: python-3.xlistfiltermissing-data

解决方案


要求有点不清楚,所以我不能 100% 确定这完全符合您的要求,但这是我目前最好的猜测。

def get_right_number(numbers, i):
""" Recursive function to search for the first valid number to the right """

    if i >= len(numbers) - 1:
        right = -99
    else:
        right = numbers[i + 1]
        if right == -99:
            right = get_right_number(numbers, i+1)
    return right


def clean_missing_data(numbers):
    print(f'Input: {numbers}')

    if all(x == -99 for x in numbers):
        print('All values in list are invalid. Could not compute.')
        return

    clean_numbers = []

    for i in range(len(numbers)):
        if numbers[i] != -99:
            clean_numbers.append(numbers[i])
        else:
            valid_count = 0

            if i == 0:
                left = 0
            else:
                left = clean_numbers[i - 1]
                valid_count += 1

            right = get_right_number(numbers, i)
            if right == -99:
                right = 0
            else:
                valid_count += 1

            average = (left + right) / valid_count
            clean_numbers.append(average)

    print(f'Output: {clean_numbers}\n')
    return clean_numbers

这是我的测试用例(打印嵌入在上面的 clean 方法中):

clean_missing_data([1, 2, 3, 4, 5])
clean_missing_data([1, 2, 3, -99, 5])
clean_missing_data([-99, 2, 3, 4, 5])
clean_missing_data([-99, -99, 3, 4, 5])
clean_missing_data([1, 2, 3, 4, -99])
clean_missing_data([1, 2, 3, -99, -99])
clean_missing_data([1, -99, -99, -99, 5])
clean_missing_data([-99, -99, -99, -99, -99])

以下是输出:

Input: [1, 2, 3, 4, 5]
Output: [1, 2, 3, 4, 5]

Input: [1, 2, 3, -99, 5]
Output: [1, 2, 3, 4.0, 5]

Input: [-99, 2, 3, 4, 5]
Output: [2.0, 2, 3, 4, 5]

Input: [-99, -99, 3, 4, 5]
Output: [3.0, 3.0, 3, 4, 5]

Input: [1, 2, 3, 4, -99]
Output: [1, 2, 3, 4, 4.0]

Input: [1, 2, 3, -99, -99]
Output: [1, 2, 3, 3.0, 3.0]

Input: [1, -99, -99, -99, 5]
Output: [1, 3.0, 4.0, 4.5, 5]

Input: [-99, -99, -99, -99, -99]
All values in list are invalid.

请注意,当您有一串无效数字时,我们将获取最右边的有效数字并取平均值。在计算下一个数字等时会考虑这个新的平均值。这执行了一种插值,但严格来说它不是线性插值。如果没有完整的要求,现在就必须这样做(按时且在预算内!)

如果您需要更改需求,您可以调整上面的代码,直到所有测试用例都满足您的需求。我也确信有一种更清洁的方法可以做到这一点,但我会把它留给你去弄清楚。祝你好运!


推荐阅读