Как умножить строки данных в массиве на основе «атрибута» строки? - PullRequest
2 голосов
/ 06 марта 2020

У меня есть большой pandas DF, который занимает почти всю мою оперативную память. Его индекс всегда один из следующих: «c1», «c2», «c3».

    0   1   2  ...  n
i            
c1  1   8  15
c2  2   9  16
c1  3  10  17
c3  4  11  18
c2  5  12  19
c1  6  13  20
c3  7  14  21
...

У меня также есть словарь, в котором ключи «соответствуют» индексным меткам фрейма данных. Значения представляют собой списки / массивы с длиной n (равной количеству столбцов данных).

d = {'c1':[10,10,10,...],'c2':[100,100,100,...],'c3':[1000,1000,1000,...]}

len(d[<allkeys>]) == n >>> True

Я хочу сделать простое умножение данных на основе «атрибута» строки - в этом case это его индекс, но это может быть значение из столбца. Результат будет выглядеть следующим образом:

       0      1      2
i                     
c1    10     80    150
c2   200    900   1600
c1    30    100    170
c3  4000  11000  18000
c2   500   1200   1900
c1    60    130    200
c3  7000  14000  21000

Я не хочу создавать второй DF2 для фрейма данных таким образом, чтобы я мог просто сделать DF * DF2, потому что у меня недостаточно ОЗУ и потому что датафрейм кажется мне бессмысленным, а это означает, что это будет просто повторение массивов / списков (пожалуйста, исправьте меня, если я ошибаюсь).

Я думал о втором кадре данных, подобном этому:

       0     1     2
c1    10    10    10
c2   100   100   100
c3  1000  1000  1000

Но когда я делаю DF * DF2, каким-то образом индекс сортируется, и я не знаю, как этого можно избежать. Результат:

          0         1         2
c1      100       800      1500
c1      300      1000      1700
c1      600      1300      2000
c2    20000     90000    160000
c2    50000    120000    190000
c3  4000000  11000000  18000000
c3  7000000  14000000  21000000

Если вы считаете, что есть другой способ решения этой проблемы (различные структуры данных, библиотеки и т. Д. c), который также будет полезен.

Код для примеров:

df = pd.DataFrame({0: [1, 2, 3, 4, 5, 6, 7],1: [8, 9, 10, 11, 12, 13, 14], 2: [15, 16, 17, 18, 19, 20, 21]}, index=pd.Index(['c1', 'c2', 'c1', 'c3', 'c2', 'c1', 'c3'], dtype='object', name='i'))
d = {'c1':[10,10,10],'c2':[100,100,100],'c3':[1000,1000,1000]}
df2 = pd.DataFrame.from_dict(d,orient='index')

Ответы [ 2 ]

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

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

Поэтому я бы:

  • сохранил большой фрейм данных в файл csv на диске и удалил его из памяти
  • , открыв CSV-файл, чтобы прочитать его по чанкам
  • открыть новый CSV-файл, чтобы сохранить результат (с пустой копией кадра данных)
  • , а затем разделить на куски:
    • прочитать кусок
    • обработать его
    • добавить его в новый CSV-файл

Конечно, не такой эффективный, как покупка большего количества памяти, но надежный и масштабируемый.

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

Идея является дедупликатным индексом на DataFrame.set_index, кратным DataFrame.mul на первый уровень и последним удалением второго уровня на DataFrame.reset_index:

df1 = (df.set_index(np.arange(len(df)), append=True)
         .mul(df2, level=0)
         .reset_index(level=1, drop=True))
print (df1)
       0      1      2
i                     
c1    10     80    150
c2   200    900   1600
c1    30    100    170
c3  4000  11000  18000
c2   500   1200   1900
c1    60    130    200
c3  7000  14000  21000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...