2016-11-09 2 views
1

Я дам минимальный пример, где я бы создал массивы numpy внутри элементов строки из pandas.DataFrame.pandas, правильно обрабатывать массивы numpy внутри элемента строки

TL; ДР: см скриншота DataFrame

Этот код находит минимум некоторой функции, с помощью scipy.optimize.brute, который возвращает минимум, переменные, в которой минимум найдены и два Numpy массивов, на которых он оценил функцию.

import numpy 
import scipy.optimize 
import itertools 

sin = lambda r, phi, x: r * np.sin(phi * x) 

def func(r, x): 
    x0, fval, grid, Jout = scipy.optimize.brute(
     sin, ranges=[(-np.pi, np.pi)], args=(r, x), Ns=10, full_output=True) 
    return dict(phi_at_min=x0[0], result_min=fval, phis=grid, result_at_grid=Jout) 


rs = numpy.linspace(-1, 1, 10) 
xs = numpy.linspace(0, 1, 10) 

vals = list(itertools.product(rs, xs)) 

result = [func(r, x) for r, x in vals] 

# idk whether this is the best way of generating the DataFrame, but it works 
df = pd.DataFrame(vals, columns=['r', 'x']) 
df = pd.concat((pd.DataFrame(result), df), axis=1) 
df.head() 

dataframe

Я ожидаю, что это не так, как я должен делать это и должно, возможно, расширить списки каким-то образом. Как я могу справиться с этим правильным, красивым и чистым способом?

+2

Не уверен, что вопросы подотчетен в своей нынешней форме - то, что вы ожидаете выхода на выглядит как? «Красивая и чистая» может быть очень в глазах смотрящего ... –

ответ

1

Итак, хотя «прекрасный и чистый» подлежит интерпретации, я дам вам свое, что должно дать вам в свою очередь некоторые идеи. Я использую multiindex, чтобы впоследствии вы могли легко выбирать пары phi/result_at_grid для каждой точки в оценочной сетке. Я также использую apply вместо создания двух фреймов данных.

import numpy 
import scipy.optimize 
import itertools 

sin = lambda r, phi, x: r * np.sin(phi * x) 

def func(row): 
    """ 
    Accepts a row of a dataframe (a pd.Series). 
    df.apply(func, axis=1) 
    returns a pd.Series with the initial (r,x) and the results 
    """ 
    r = row['r'] 
    x = row['x'] 
    x0, fval, grid, Jout = scipy.optimize.brute(
     sin, ranges=[(-np.pi, np.pi)], args=(r, x), Ns=10, full_output=True) 

    # Create a multi index series for the phis 
    phis = pd.Series(grid) 
    phis.index = pd.MultiIndex.from_product([['Phis'], phis.index]) 

    # same for result at grid 
    result_at_grid = pd.Series(Jout) 
    result_at_grid.index = pd.MultiIndex.from_product([['result_at_grid'], result_at_grid.index]) 

    # concat 
    s = pd.concat([phis, result_at_grid]) 

    # Add these two float results 
    s['phi_at_min'] = x0[0] 
    s['result_min'] = fval 

    # add the initial r,x to reconstruct the index later 
    s['r'] = r 
    s['x'] = x 

    return s 



rs = numpy.linspace(-1, 1, 10) 
xs = numpy.linspace(0, 1, 10) 

vals = list(itertools.product(rs, xs)) 
df = pd.DataFrame(vals, columns=['r', 'x']) 

# Apply func to each row (axis=1) 
results = df.apply(func, axis=1) 
results.set_index(['r','x'], inplace=True) 
results.head().T # Transposing so we can see the output in one go... 

enter image description here

Теперь вы можете выбрать все значения в точке сетки оценки 2, например

print(results.swaplevel(0,1, axis=1)[2].head()) # Showing only 5 first 


        Phis result_at_grid 
r x         
-1.0 0.000000 -1.745329  0.000000 
    0.111111 -1.745329  0.193527 
    0.222222 -1.745329  0.384667 
    0.333333 -1.745329  0.571062 
    0.444444 -1.745329  0.750415 
+1

Большое спасибо, да, это определенно дает мне некоторое вдохновение в том, как бороться с этой проблемой! :) – johnbaltis

Смежные вопросы