#python #pandas #performance #data-cleaning
#python #pandas #Производительность #очистка данных
Вопрос:
Я новичок в науке о данных, я пытался выполнить некоторую очистку данных, и у меня был столбец лет в моем фрейме данных. Предположительно, год должен быть целым числом, но, поскольку есть некоторые значения NA, он автоматически обозначается как float . Интересно, лучше ли преобразовать его в nullable int like pd.Int32Dtype()
или оставить его плавающим. Есть ли какая-либо разница с точки зрения производительности?
Ответ №1:
Я построил два основных примера, оба с одинаковыми данными. Я создал a DataFrame
из 1-мерного массива размером 500 000. Я также присвоил None
нескольким элементам массива.
Построение данных:
import time
import pandas as pd
years = [i for i in range(0, 500000)]
years[23] = None
years[44] = None
years[151] = None
Int:
start = time.perf_counter()
df_int = pd.DataFrame(data = years, dtype = pd.Int32Dtype())
finish = time.perf_counter()
print(f'Finished in {finish-start}')
# Finished in 0.17838970199999993
Float:
start = time.perf_counter()
df_float = pd.DataFrame(data = years)
finish = time.perf_counter()
print(f'Finished in {finish-start}')
# Finished in 0.07671123900000004
Из выходных данных преобразование данных в pd.Int32Dtype()
явно медленнее.
Однако время, необходимое для представления этого массива из 500 000 элементов Int32Dtype
, все еще было очень быстрым для большого массива. Это очень простой пример, поскольку в реальных данных будет намного больше столбцов, вложенных массивов и т. Д. Это особенно верно для науки о данных, поскольку наборы данных машинного обучения могут быть чрезвычайно большими и многомерными.
Редактировать:
Поскольку вы работаете с пропущенными значениями, вы, скорее всего, будете использовать методы, которые, ну, имеют дело с пропущенными значениями в ваших данных.
Я настроил скрипт, который усредняет время, затраченное на удаление недостающих значений и сброс индекса фрейма данных. Усреднение было выполнено с использованием времени из 200 запусков. Размер массива остается таким же, как и раньше: 500 000. На этот раз отличается то, что я сделал каждое значение, которое равномерно делится на 200 None
. Это означает None
, что в этом массиве 2500 отображений.
years = [None if i%200 == 0 else i for i in range(0, 500000)]
Int:
times = []
for i in range(0,200):
df_int = pd.DataFrame(data = years, dtype = pd.Int32Dtype(), columns=['years'])
start = time.perf_counter()
df_int.dropna(inplace=True)
df_int.reset_index(drop=True, inplace=True)
finish = time.perf_counter()
times.append((finish-start))
Float:
times = []
for i in range(0,200):
df_float = pd.DataFrame(data = years, columns=['years'])
start = time.perf_counter()
df_float.dropna(inplace=True)
df_float.reset_index(drop=True, inplace=True)
finish = time.perf_counter()
times.append((finish-start))
Средние значения были взяты следующим образом:
avg = sum(times)/len(times)
Результаты были следующими:
# Float: 0.009853112889999979
# Int: 0.009194320404999973
Ресурсы:
Работа с отсутствующими данными
Комментарии:
1. спасибо за ваш ответ, хотя было приятно узнать, что преобразование в float происходит быстрее, моя проблема была немного другой. при загрузке набора данных в столбце уже был тип float, и мне было интересно, влияет ли тип данных на производительность. более конкретно, есть ли какая-либо разница при выполнении вычислений с помощью pd.Int32Dtype() по сравнению с float?