Более быстрое преобразование столбцов pandas на основе значений столбцов, чем итерация?

#python #pandas #dataframe #type-conversion

Вопрос:

У меня есть поток событий:

 unixtimestamp, eventname, type Array<>, value Array<>
1595235332848,event1, ['Boolean','Boolean'], ['True','['True','False']']
1595235333254,event1, ['Boolean','Boolean'], ['True','['True','True']']
1595235333785,event2, ['Float64','Float64'], ['0.0','123.12323']
 

В начале все имеет тип str или массив строк. Я использую сводную таблицу для построения огромной таблицы (~18 столбцов, >1 млн. строк):

 def aggfunc(self, x):
    value_str = ' '.join(str(y) for x in np.unique(x.values) for y in x)
    return value_str
pivot_df = data_df.pivot_table(values=['value', 'type'],index=['unixtimestamp'], columns=['eventname'], aggfunc=self.aggfunc)
#Gives me two DFs DF['value'] and DF['type'] with all columns
print(pivot_df.shape)
conversion_arr = {}
typings_to_python_types_arr = {'Boolean': 'bool', 'Byte': 'bytes', 'ByteString': 'bytes', 'DateTime': 'datetime64[ns]', 'Double': 'float64', 'Float': 'float64', 'Int16': 'int16', 'Int32': 'int32', 'Int64': 'int64', 'SByte': 'str', 'String': 'str', 'UInt16': 'uint16', 'UInt32': 'uint32' }
for column in pivot_df['type'].columns:
      conversion_arr[column] = typings_to_python_types_arr [pivot_df['type'][column].unique()[0]]
pivot_df['value'].astype(conversion_arr)
 

На данный момент я создаю диктант для приведения в действие итеративным способом, что чертовски медленно для 6 тыс. столбцов. Это занимает около 5 минут. Я использую первый уникальный элемент серии типов и устанавливаю его в качестве типа python для соответствующего столбца. После этого я сразу же бросаю огромный стол, что происходит быстро. Но итерация по всем вызовам столбцов/уникальности занимает так много времени. Есть ли шанс ускорить процедуру?

P. S: В моей функции aggfunc также есть замечание, что при наличии разных неидентичных значений создается строка, разделенная пробелом, что приводит к сбою преобразования. Любые дополнительные идеи по этому дополнительному вопросу приветствуются.

Редактировать:// Ожидаемый результат, что было бы неплохо:

 unixtimestamp,  event1/value,  event2/value
1595235332848, [(dtype boolean)True, (dtype list(boolean))[True, False]], NaN
1595235333254, [(dtype boolean)True, (dtype list(boolean))[True, True ]], NaN
1595235333785, NaN                                                      , [(dtype float64)0.0, (dtype float64)123.12323]
 

или лучше всего будет распакованная версия:

 unixtimestamp,  event1/value,  event2/value
1595235332848, [(dtype boolean)True, (dtype boolean)True, (dtype boolean)False], NaN
1595235333254, [(dtype boolean)True, (dtype boolean)True, (dtype boolean)True ], NaN
1595235333785,  NaN                                                            , [(dtype float64)0.0, (dtype float64)123.12323]
 

Комментарии:

1. Можете ли вы дать код, который создает ваш входной фрейм данных, а также ожидаемый результат от этого примера ввода?

2. Вы говорите, что «используете первый уникальный элемент серии типов» — вы используете np.unique(x.values) , и pivot_df['type'][column].unique()[0] это означает, что сначала ему нужно пройти >1 млн записей x 18 тыс. раз, дважды. Возможно, меньше итераций на поворотном df. Подумайте о том, чтобы свести это к принятию только 1-го ненулевого, ненулевого или нетривиального значения. Выполнение этого 18 раз не должно быть таким медленным.

3. функция pivot_table работает быстро, потому что np.unique() вызывается для ряда Проблема не в этом. Проблема заключается в том, что для выполнения цикла for по столбцам типа требуется много времени для создания conversion_arr.

4. @Скотт Бостон добавил пример вывода. Банкомат, я не могу предоставить вам функцию генератора, извините. Я должен написать один, позже.

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