Pandas: применить функцию к нескольким столбцам разных фреймов данных - PullRequest
0 голосов
/ 15 марта 2020

У меня есть класс, который возвращает значение путем сравнения различных значений. Класс:

class feasible:
    def __init__(self,old_difference, for_value, back_value, fall_back_value):
        self.diff=abs(for_value-back_value)
        for_diff=abs(for_value-fall_back_value)
        back_diff=abs(back_value-fall_back_value)
        if self.diff < old_difference:
            self.value=(for_value+back_value)/2
        elif for_diff<back_diff:
            self.value=(for_value)
        else:
            self.value=(back_value)

Как применить этот класс и вернуть значение , если входные данные представляют собой столбцы из разных фреймов данных?

Все входные фреймы в следующем формате:

   x         y          theta
0  0.550236 -4.621542   35.071022
1  5.429449 -0.374795   74.884065
2  4.590866 -4.628868  110.697109

Я пробовал следующее, но возвращает ошибку ( Ошибка : Значение истинности Серии неоднозначно ) из-за проводится сравнение.

feasible_x=feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
filler_frame.x=feasible_x.value

1 Ответ

1 голос
/ 15 марта 2020

В настоящее время ваш метод ожидает получения скалярных значений, но вы передаете Pandas Series (т. Е. Столбцы фреймов данных) в метод. Следовательно, if logi c должен проверять каждый элемент Серии (структура много значений одного типа), а не одно значение. Следовательно, вы получаете ошибку неоднозначного значения истины. Новички Pandas часто сталкиваются с этой ошибкой общего назначения Python. Pandas / Numpy поддерживает объектную модель, отличную от общей Python.

Чтобы разрешить, потому что вы по сути вычисляете новые поля с условными логами c, рассмотрите возможность связывания всех параметров Series в один фрейм данных. Затем замените общую Python конструкцию if...elif...else для numpy.where, которая запускает logi c для объектов более высокого размера, таких как массивы.

class feasible:
    def __init__(self, old_difference, for_value, back_value, fall_back_value):
        # HORIZONTAL MERGE (OUTER JOIN) ON INDEX
        x_frame = (pd.concat([old_difference, for_value, back_value, fall_back_value], axis = 1)
                     .set_axis(['old_difference', 'for_value', 'back_value', 'fall_back_value'],
                               axis = 'columns', inplace = False)
                  )

        # ASSIGN NEW CALCULATED COLUMNS
        x_frame['diff'] = (x_frame['for_value'] - x_frame['back_value']).abs()
        x_frame['for_diff'] = (x_frame['for_value'] - x_frame['fall_back_value']).abs()
        x_frame['back_diff'] = (x_frame['back_value'] - x_frame['fall_back_value']).abs()

        # ASSIGN FINAL SERIES BY NESTED CONDITIONAL LOGIC
        self.value = np.where(x_frame['diff'] < x_frame['old_difference'],
                              (x_frame['for_value'] + x_frame['back_value'])/2,
                              np.where(x_frame['for_diff'] < x_frame['back_diff'],
                                       x_frame['for_value'],
                                       x_frame['back_value']
                                      )
                              )

Теперь в зависимости от размер строки всех четырех фреймов данных, различные реализации результата должны быть обработаны. В частности, pd.concat при axis = 1 по умолчанию работает на join='outer', поэтому все строки сохраняются в операции горизонтального слияния с NaN, заполненным для несопоставленных строк.

  • Если filler_frame (фрейм данных, в который вы собираетесь добавить столбец), равны всем строкам, тогда простое присвоение выполнимо.

    # IF filler_frame CONTAINS THE MOST ROWS (OR EQUIVALENT TO MOST) OF ALL FOUR DFs
    feasible_x = feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
    filler_frame['x_new'] = feasible_x.value
    
  • Если нет левого соединения для нового столбца, требуется x_new . Ниже будет работать во всех случаях, включая выше.

    # IF filler_frame DOES NOT CONTAIN MOST ROWS OF ALL FOUR DFs
    feasible_x = feasible(diff_frame.x,for_frame.x,back_frame.x,filler_frame.x)
    filler_frame = filler_frame.join(pd.Series(feasible_x.value).rename('x_new'), how = 'left')
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...