Создать фрейм данных из другого фрейма с промежуточными вычислениями - PullRequest
0 голосов
/ 11 июня 2018

Скажем, у меня есть данные в фрейме данных Pandas, с которыми я хочу работать.

>>> df = pd.DataFrame([['a',10,5],['a',12,6],['b',4,2],['b',5,10]],
...                   columns=['id','val','val2']))

Итак, фрейм данных выглядит примерно так:

>>> df
    id   val   val2
0   a    10    5
1   a    12    6
2   b    4     2
3   b    5     10

Чего я хочу достичьявляется фреймом данных, содержащим значения id в качестве имен столбцов и val и val2 в качестве имен строк, где значения должны быть составлены следующим образом:

  1. Построить среднее значениедля столбцов значений, основанных на id, оставляя что-то вроде

    id   mean-val   mean-val2
    a    11         5.5
    b    4.5        6
    
  2. Рассчитать процент mean-val и mean-val2 от суммы обоих значений на основе id (например, 11 / (11+5.5) * 100 = 66.67), рендеринг

    id    perc-val   perc-val2
    a     66.67      33.33
    b     42.86      57.14
    

Окончательный кадр данных должен выглядеть следующим образом:

>>> new_df
       a       b
val    66.67   42.86
val2   33.33   57.14

Мой подход

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

>>> idx = ['val','val2']
>>> lst = [df.groupby('id')[index].mean() for index in idx]
>>> df_new = pd.DataFrame(
...     [[x/y*100 for x, y in zip(lst2,sum(lst))] for lst2 in lst],
...     index=idx, columns=df['id'].unique())

Это работает, но я не уверен, гарантируется ли, что в столбце или строке названы имена вв правильном порядке или, если возможно, например, столбец a имеет имя b и наоборот.

Таким образом, мой актуальный вопрос: есть ли более хороший, чистый, безопасный и, возможно, более эффективный способ сделать это.

1 Ответ

0 голосов
/ 11 июня 2018

Да, есть.

  1. Если вы берете среднее значение для каждого столбца, вам не нужно указывать имена столбцов
  2. Вы можете векторизовать свое деление, используяDataFrame.div (или оператор деления __div__)

v = df.groupby('id').mean()
v.T / v.sum(1) * 100          # thanks to @fuglede
# v.div(v.sum(1), axis=0).T   # thanks to @Scott Boston

id            a          b
val   66.666667  42.857143
val2  33.333333  57.142857
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...