Эффективный метод многоуровневой линейной интерполяции в Python - PullRequest
1 голос
/ 30 апреля 2019

В настоящее время я работаю над проектом по оценке неопределенности расходомера.Погрешность измерителя основана на четырех различных значениях:

  1. Расход жидкости (ликв.)
  2. Вязкость жидкости (сП)
  3. Соотношение вода-жидкость (wlr)
  4. Объемная доля газа (gvf)

Третья сторона предоставляет таблицы для счетчика с несколькими различными значениями для liq, cP, wlr и gvf.Как вы можете догадаться, данные со счетчика никогда не попадают в одно из предопределенных значений.Например, минута данных может выглядеть следующим образом:

  1. Расход жидкости: 6532
  2. Вязкость жидкости: 22 * ​​1018 *
  3. Соотношение воды и жидкости: 0,412
  4. ГазФракция объема: 0,634

С данными выше, для определения неопределенности выполняется четырехсторонняя интерполяция по таблицам.

Я нашел решение, но оно кажется неуклюжим, и мне интересно, есть ли у кого-нибудь идеи.Я все еще новичок в игре «Панды» и очень ценю возможность увидеть решения других людей.

Сначала я сортирую данные, чтобы уменьшить таблицу до значений выше и ниже фактической точки, которую я ищу.

aliq = 6532 # stbpd
avisc = 22 # centipoise
awlr = 0.412 # water liquid ratio
agvf = 0.634 # gas volume fraction

def findclose(num, colm):

    arr = colm.unique()

    if num in arr:
        clslo = num
        clshi = num

    else:
        clslo = arr[arr > num].min() # close low value
        clshi = arr[arr < num].max() # close high value

    return [clslo, clshi]

df = tbl_vx52[
    (tbl_vx52['liq'].isin(findclose(aliq,tbl_vx52['liq']))) & 
    (tbl_vx52['visc'].isin(findclose(avisc,tbl_vx52['visc']))) & 
    (tbl_vx52['wlr'].isin(findclose(awlr,tbl_vx52['wlr']))) & 
    (tbl_vx52['gvf'].isin(findclose(agvf,tbl_vx52['gvf'])))
                   ].reset_index(drop=True)

Таблица уменьшена с 2240 до 16 значений.Вместо включения всех данных (tbl_vx52).Я создал некоторый код для загрузки, чтобы вы могли видеть, как выглядит подкадр данных, называемый df, только со значениями выше и ниже областей для этого примера.

df = pd.DataFrame({'liq':[5000, 5000, 5000, 5000, 5000, 5000, 5000, 5000, 7000, 7000, 7000, 7000, 7000, 7000, 7000, 7000],
                  'visc':[10, 10, 10, 10, 30, 30, 30, 30, 10, 10, 10, 10, 30, 30, 30, 30],
                  'wlr':[0.375, 0.375, 0.5, 0.5, 0.375, 0.375, 0.5, 0.5, 0.375, 0.375, 0.5, 0.5, 0.375, 0.375, 0.5, 0.5],
                  'gvf':[0.625, 0.75, 0.625, 0.75, 0.625, 0.75, 0.625, 0.75, 0.625, 0.75, 0.625, 0.75, 0.625, 0.75, 0.625, 0.75],
                  'uncert':[0.0707, 0.0992, 0.0906, 0.1278, 0.0705, 0.0994, 0.091, 0.128, 0.0702, 0.0991, 0.0905, 0.1279, 0.0704, 0.0992, 0.0904, 0.1283],
                  })

Произведено довольно грубое зацикливаниеначать сопряжение значений на основе отдельных входов (liq, visc, wlr или gvf).Ниже показан первый цикл gvf.

pairs = [
    slice(0,1),
    slice(2,3),
    slice(4,5),
    slice(6,7),
    slice(8,9),
    slice(10,11),
    slice(12,13),
    slice(14,15)]

for pair in pairs:

    df.loc[pair,'uncert'] = np.interp(
        agvf, 
        df.loc[pair,'gvf'], 
        df.loc[pair,'uncert']
    )
    df.loc[pair,'gvf'] = agvf

df = df.drop_duplicates().reset_index(drop=True)

Дублирующиеся значения удаляются, уменьшаясь с 16 строк до 8 строк.Затем это повторяется снова для wlr.

pairs = [
    slice(0,1),
    slice(2,3),
    slice(4,5),
    slice(6,7)
]

for pair in pairs:

    df.loc[pair,'uncert'] = np.interp(
        awlr, 
        df.loc[pair,'wlr'], 
        df.loc[pair,'uncert']
    )
    df.loc[pair,'wlr'] = awlr

df = df.drop_duplicates().reset_index(drop=True)

Структура выше повторяется для visc (четыре строки) и, наконец, жидкости (две строки), пока не останется только одно значение в подмассиве.Что дает неопределенность в метрах в вашей рабочей точке.

Я знаю, это довольно неуклюже.Любой вклад или мысли о различных методах приветствуется.

...