df.iloc быстрее или массив numpy?

#python #pandas #performance #numpy

#python #панды #Производительность #numpy

Вопрос:

У меня есть csv-файл, который выглядит следующим образом:

 id    date        feature1 feature2 feature3
A1    01-01-2019  1        2        3
A2    01-01-2019  3        4        5
A1    01-02-2019  6        7        8
 

(Я составил эти цифры)

Я хотел бы сформировать 3D-массив, где одна ось — идентификатор, другая ось — дата, другие функции. В приведенном выше примере это будет выглядеть так

 1 2 3
3 4 5
 

для дня 1,

 6   7   8
nan nan nan
 

на 2-й день.

Итак, у меня был бы массив 2x2x3 (2 идентификатора, 2 дня, 3 функции).

Мои реальные данные имеют 800000 метров, 365 дней и 6 функций. У меня также есть словарь, dict_id , который связывает идентификатор с индексом.

Моя реализация выглядит следующим образом:

 data = pd.read_csv('data.csv')
data['date'] = pd.to_datetime(data['date'])
data['date'] = data['date'].dt.dayofyear

a,b = data.shape

output = np.full((800000,365,6),np.nan)

for i in range(a):
   output[dict_id[data.iloc[i,0]],data.iloc[i,1],:] = data.iloc[i,2::]
 

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

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

1. Как только у вас появляется цикл Python, вы теряете все возможности Pandas или numpy. Можно ли использовать объект или функцию numpy вместо поиска в dict_id ?

2. Почему бы просто не придерживаться pandas и не сделать что-то вроде reindex и использовать a MultiIndex , чтобы получить тот же тип организации, что и с массивом numpy

3. @SergeBallesta как это будет выглядеть? Словарь просто связывает идентификатор счетчика, который представляет собой строку с индексом. Индекс может быть любым, что означает: идентификатор A1 может иметь индекс 0 или 1. @ALollz как это будет выглядеть? Я использовал цикл for, потому что я действительно не знаю, как использовать другие параметры.

Ответ №1:

Одна вещь, которую вы можете сделать, это обратиться dict_id к ряду и отпустить for цикл:

 s = pd.Series(dict_id)

output[s[data.iloc[:,0]] , data.iloc[:,1], :] =  data.iloc[:, 2::]
 

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

1. конечно! Я попробую и посмотрю, насколько это быстрее.

2. Да, это намного быстрее!