Более эффективный способ, чем построчное вычисление Pandas Dataframe - PullRequest
0 голосов
/ 03 октября 2018

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

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

До сих пор я делаю все это в большом цикле for для каждого подмножества данных, а затем присваиваю результаты построчнона фрейм данных.

Что я хочу знать, есть ли более эффективный способ сделать это?Я также не хочу иметь много копий данных, так как часто у меня есть миллион точек данных или около того.

Я создал очень упрощенный пример с искусственными данными и без оценки максимального правдоподобия, но этопоказывает базовую структуру

import pandas as pd
import scipy as sp

import numpy.random as sprd

def Gen_UniformDist(seed=5, size=1000000):
    """ Create a set of random numbers uniformly distributed between 0 and 1 """
    sprd.seed(seed)    
    return sprd.uniform(size=size)

# Generate some test data
dataSet = Gen_UniformDist()

# Create an array of truncation vales
truncValue_arr = sp.linspace(0., 0.9, 20)

df_Output = pd.DataFrame(index=truncValue_arr, columns=['mean', 'NumObs'])

for i, truncValue in enumerate(truncValue_arr):
    # Truncate the data using the truncation value
    truncated_DataSet = dataSet[ dataSet >= truncValue]

    # In my real code the function here is more complex max likelihood 
    # rather than simple mean used for simplicity here
    mean = sp.mean(truncated_DataSet)

    numObs = len(truncated_DataSet)

    # Real code would calculate more than 2 values for each row
    df_Output.iloc[i] = [mean, numObs]

То, что я хотел бы сделать, это эффективно заполнить фрейм данных без цикла for, но также избегать большого количества копий данных.Это возможно?

1 Ответ

0 голосов
/ 03 октября 2018

Есть два аспекта вашего алгоритма, которые можно оптимизировать сразу:

  1. Заменить цикл for на понимание списка.
  2. Вместо повторных вызовов iloc,создайте список кортежей и подайте на pd.DataFrame напрямую.

Вот некоторый псевдокод:

def return_values(data):
    return sp.mean(data), len(data.index)

L = [return_values(dataSet[dataSet >= truncValue]) for truncValue in truncValue_arr]

df = pd.DataFrame(data=L, index=truncValue_arr, columns=['mean', 'NumObs'])

Вы можете оптимизировать дальнейшее путем рефакторинга dataSet >= truncValue, который происходит в каждомпетля.Рассмотрим следующее:

s = pd.Series([1, 2, 3, 4, 5])
vals = np.array([2, 4])

s[:, None] > vals

array([[False, False],
       [False, False],
       [ True, False],
       [ True, False],
       [ True,  True]], dtype=bool)

Поэтому вы можете сделать что-то вроде:

mask = np.array(dataset)[:, None] >= np.array(truncValue_arr)

L = [return_values(dataset.loc[mask[:, i]]) \
     for i, truncValue in enumerate(truncValue_arr)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...