Вопрос об удалении сценария оптимизации панд для цикла (iterrows, zip, ...) - PullRequest
0 голосов
/ 11 февраля 2019

Я ищу способ ускорить мой сценарий в pandas dataframe.

Чтобы понять ситуацию, я проиллюстрирую два набора данных, которые участвуют в сценарии.

Сначала у нас есть"entrydata", это список вещей, которые мы купили.который имеет столбец с именем «date», столбец с именем «id» и столбец с именем «value», как в таблице выше:

<table>
  <tr>
    <th>Date</th>
    <th>Id</th> 
    <th>Value</th>
  </tr>
  <tr>
    <td>01/01/2017</td>
    <td>111</td> 
    <td>58.4</td>
  </tr>
  <tr>
    <td>01/01/2017</td>
    <td>222</td> 
    <td>120.7</td>
  </tr>
  <tr>
    <td>02/18/2017</td>
    <td>111</td> 
    <td>59.3</td>
  </tr>
  <tr>
    <td>02/18/2017</td>
    <td>222</td> 
    <td>130.8</td>
  </tr>
  <tr>
    <td>04/13/2017</td>
    <td>111</td> 
    <td>59.3</td>
  </tr>
  <tr>
    <td>04/13/2017</td>
    <td>222</td> 
    <td>130.8</td>
  </tr>
</table>

Другие данные, которые у нас есть, это «outdata», то есть список вещей, которые мы продаем, у нас есть столбец с именем «date», столбец с именем «id»"и столбец с именем" значение ", как в таблице выше:

<table>
  <tr>
    <th>Date</th>
    <th>Id</th> 
    <th>Value</th>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>111</td> 
    <td>60</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>111</td> 
    <td>60</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>111</td> 
    <td>60</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>222</td> 
    <td>122</td>
  </tr>
  <tr>
    <td>01/03/2017</td>
    <td>222</td> 
    <td>122</td>
  </tr>
  <tr>
    <td>02/25/2017</td>
    <td>222</td> 
    <td>122</td>
  </tr>
  <tr>
    <td>02/25/2017</td>
    <td>111</td> 
    <td>70</td>
  </tr>
  <tr>
    <td>02/25/2017</td>
    <td>222</td> 
    <td>135</td>
  </tr>
</table>

С этими наборами данных я написал скрипт, который использовал цикл for, как показано выше:

for row in tqdm(zip(dbOut["Date"],dbOut["Id"],dbOut["Value"])):
    dateOut = row[0]
    idOut = row[1]
    valueOut = row[2]

    #get all entry rows that have idOut id
    dbSample = dbEntry.loc[dbEntry["Id"] == idOut]

    #now do the mean of the column Value
    result = dbSample["Value"].mean()

    #append to an array created before the loop
    valuefinal.append(result)

#out of loop we put it in the outdata dataFrame in a new column
dbOut["FinalValue"] = valuefinal

По сути, это то, что делает скрипт,В кадрах входа и выхода есть больше столбцов, но с этим примером я думаю, что я возобновил происходящее.

Этот код отлично работает с точки зрения результата, но я хотел бы ускорить его.Сначала код был написан с использованием цикла iterrows.Ища способ ускориться, я увидел, что iterrows был плохим выбором.Так что я перешел на itertuples, а затем на функцию zip.

Все это работает с точки зрения результата, но время итераций не сильно изменилось.я говорю о 300 итерациях в секунду.

Чем я изменил часть кода, используя векторизацию, и в зависимости от входных данных я получил увеличение от 600 до 1200 итераций в секунду.

некоторую часть кода можно было векторизовать, а другую - нет!Часть, которая могла быть векторизована, была той, которая делает простое вычитание, используя два других столбца.

Часть, которая использовала уменьшенный кадр данных с определенным Id, который я не мог векторизовать, потому что это показывало следующую ошибку:

ValueError: Может сравнивать только идентично помеченные объекты Series

Код, который я пытался векторизовать, я просто удалил из цикла и внес необходимые изменения.Вот оригинальный код внутри цикла:

result = dbSample["Value"].mean

А вот код, который я пытался векторизовать, удаляя цикл:

dbOut["FinalValue"] = dbEntry.loc[dbEntry["Id"] == dbOut["Id"]]["Value"].mean()

Наконец, к вопросу.Могу ли я сделать этот вид векторизации с определенной частью кадра данных (entryData)?Любые предложения, чтобы сделать код работает быстрее?Как 3000iterations / секунда?

Заранее спасибо!

1 Ответ

0 голосов
/ 11 февраля 2019

Я реализовал функцию apply, которая хорошо работает только с одним возвращаемым значением, когда я использую весь код, который мне нужен, я получаю ошибку.

Итак, подумав здесь, я сделал сокращение вdbOut, до запуска в цикле zip.Вместо 75000 строк dbOut я удалил дубликаты, оставив только каждый 1 столбец идентификатора, и сохранил его в dbOut2, который я применил в цикле zip.Эффективность заключается в том, что теперь мне нужно запустить только 5000 строк, что ускоряет процесс!

Теперь я попытался передать информацию из dbOut2 в de dbOut.Я использовал np.where, который я прочитал очень быстро:

dbOut["FinalValue"] = np.where(dbOut("ID") == dbOut2("ID"), dbOut2("Value"),0)

Эта строка должна работать, но у меня ничего не получилось.Любые советы о том, как правильно поместить информацию, которую я имел в dbOut2 (5000 строк) в dbOut (75000 строк)?

Еще раз спасибо!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...