Как повернуть рамку данных pandas, чтобы включить средневзвешенное значение?

Это связано с требованием отдельной компиляции и потому, что шаблоны являются полиморфизмом типа создания экземпляров.

Давайте немного приблизимся к конкретному для объяснения. Скажем, у меня есть следующие файлы:

  • foo.h объявляет интерфейс class MyClass<T>
  • foo.cpp определяет реализацию class MyClass<T>
  • bar.cpp использует MyClass<int>

. Отдельное средство компиляции. Я должен скомпилировать foo.cpp независимо от bar.cpp. Компилятор полностью выполняет всю сложную работу по анализу, оптимизации и генерации кода на каждом модуле компиляции; нам не нужно анализировать целую программу. Только компоновщик должен обрабатывать всю программу одновременно, и задача компоновщика значительно упрощается.

bar.cpp даже не нужно существовать при компиляции foo.cpp, но я все равно должен быть в состоянии связать foo.o Я уже имел вместе с bar.o Я только что выпустил, не перекомпилируя foo.cpp. foo.cpp может даже быть скомпилирован в динамическую библиотеку, распределенную где-то в другом месте без foo.cpp, и связан с кодом, который они пишут спустя годы после того, как я написал foo.cpp.

«Полиморфизм в стиле объектов» означает, что template MyClass<T> не является общим классом, который может быть скомпилирован в код, который может работать для любого значения T. Это добавит накладные расходы, такие как бокс, необходимо передать указатели на функции для распределителей и конструкторов и т. Д. Намерение шаблонов C ++ состоит в том, чтобы избежать необходимости писать почти идентичные class MyClass_int, class MyClass_float и т. Д., Но все же быть в состоянии закончить с компилируемым кодом, который в основном выглядит так, как если бы мы имели каждую версию отдельно. Таким образом, шаблон является буквально шаблоном; шаблон класса не класс, это рецепт создания нового класса для каждого T, с которым мы сталкиваемся. Шаблон не может быть скомпилирован в код, только результат создания экземпляра шаблона может быть скомпилирован.

Итак, когда foo.cpp скомпилирован, компилятор не может видеть bar.cpp, чтобы знать, что MyClass<int> необходимо. Он может видеть шаблон MyClass<T>, но он не может испускать код для этого (это шаблон, а не класс). И когда компилируется bar.cpp, компилятор может видеть, что ему нужно создать MyClass<int>, но он не может видеть шаблон MyClass<T> (только его интерфейс в foo.h), поэтому он не может его создать.

Если foo.cpp сам использует MyClass<int>, тогда код для него будет сгенерирован при компиляции foo.cpp, поэтому, когда bar.o связан с foo.o, они могут быть подключены и будут работать. Мы можем использовать этот факт, чтобы позволить конечный набор экземпляров шаблонов быть реализован в .cpp-файле, написав один шаблон. Но bar.cpp не может использовать шаблон в качестве шаблона и создавать его на всех типах, которые ему нравятся; он может использовать только ранее существовавшие версии шаблона, которые автор foo.cpp думал предоставить.

Вы можете подумать, что при компиляции шаблона компилятор должен «сгенерировать все версии», с теми, которые никогда не используются, отфильтровываются во время связывания. Помимо огромных накладных расходов и экстремальных трудностей, с которыми сталкивался такой подход, поскольку «модификаторы типа», такие как указатели и массивы, позволяют даже встроенным типам создавать бесконечное количество типов, что происходит, когда я расширяю свою программу добавив:

  • baz.cpp объявляет и реализует class BazPrivate и использует MyClass<BazPrivate>

Невозможно, чтобы это могло работать, если мы либо

  1. Необходимо перекомпилировать foo.cpp каждый раз, когда мы меняем любой другой файл в программе , в случае, если он добавил новый романный экземпляр MyClass<T>
  2. Требовать, чтобы baz.cpp содержал (возможно, через заголовок) полный шаблон MyClass<T>, чтобы компилятор мог генерировать MyClass<BazPrivate> во время компиляции baz.cpp.

Никто не любит (1), потому что системы компиляции целых программ принимают forever для компиляции и потому что это делает невозможным распространение компилированных библиотек без исходного кода. Итак, у нас есть (2).

0
задан user7289 13 July 2018 в 17:42
поделиться

2 ответа

Вот подход groupby и apply:

import pandas as pd
import numpy as np

def weighted_average(group):
    return (group["value A"] * group["value B"]).sum() / group["value B"].sum()


df = pd.DataFrame({"value A": np.random.randint(1, 100, 10),
                   "value B": np.random.randint(1, 100, 10),
                   "country": np.random.choice(["US", "UK"], 10),
                   "category": np.random.choice(["Red", "Green"], 10)},
                  index=pd.date_range("2018-01-26", "2018-02-04", num=10))
print(df)
#            category country  value A  value B
# 2018-01-26    Green      UK       74       93
# 2018-01-27    Green      UK       57        1
# 2018-01-28    Green      US        6       24
# 2018-01-29    Green      UK       31       89
# 2018-01-30    Green      UK       73       75
# 2018-01-31    Green      US       86       63
# 2018-02-01    Green      US       86       30
# 2018-02-02    Green      US       53       37
# 2018-02-03      Red      UK       50       69
# 2018-02-04      Red      US       98       33

print(df.groupby([pd.Grouper(freq='M'), "country"]).apply(weighted_average)).unstack()
# country            UK         US
# 2018-01-31  58.810078  63.931034
# 2018-02-28  50.000000  77.750000

Обратите внимание на pandas.Grouper , который группируется по месяцам (по умолчанию по индексу, но вы также можете указать столбец с помощью key="date", если вы не хотите устанавливать индекс).

Если вы также хотите разделить эту категорию по этой теме одновременно, вы можете просто добавить ее к вызову groupby (df.groupby([pd.Grouper(freq='M'), "country", "category"])...). Это сделает индекс на один уровень глубже, поэтому вам нужно решить, хотите ли вы использовать мультииндекс для столбцов или строк. Если вы хотите его на столбцах, просто добавьте еще один вызов к unstack() в конце.

1
ответ дан Graipher 17 August 2018 в 12:52
поделиться
  • 1
    Got error & quot; Только действительный с DatetimeIndex, TimedeltaIndex или PeriodIndex, но получил экземпляр 'Int64Index' & quot; есть идеи? – user7289 13 July 2018 в 21:08
  • 2
    @ user7289: Какую версию numpy и pandas вы используете? Являются ли ваши даты столбцами даты или текста (вы можете конвертировать их с помощью pandas.to_datetime, если это так). Является ли пример, который я опубликовал, не работает для вас или внутри вашего кода? Вы действительно установили дату как индекс (с df = df.set_index("date")) или передали его группе с pd.Grouper(key="date", freq="M")? – Graipher 13 July 2018 в 21:11
  • 3
    Преобразованный индекс - удивительный ответ спасибо за вашу помощь :) – user7289 13 July 2018 в 21:17
  • 4
    Одно быстрое последующее, как передать другие аргументы в функцию в приложении? – user7289 14 July 2018 в 05:56
  • 5
    @ user7289 Вы не можете, по крайней мере, не напрямую. Сначала обратите внимание, что вся группа передана, поэтому у вас есть все столбцы доступной файловой рамки. Если вам нужны другие аргументы, вам нужно предоставить их с помощью functools.partial или сделать функцию функцией, которая возвращает другую функцию. Или, как последняя солома, используйте глобальные переменные. – Graipher 14 July 2018 в 07:37

Я бы создал новый столбец mmyy - если столбец даты является датой или строкой, вам может потребоваться использовать модуль datetime. Затем группируйте по mmyy и получите общую сумму A и B, а затем создайте новый столбец, который является просто A / B

0
ответ дан Giuseppe Bonavita 17 August 2018 в 12:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: