«Развернуть» кадр данных pandas по значениям в столбце - PullRequest
0 голосов
/ 09 мая 2018

Допустим, я начинаю с фрейма данных, в котором есть некоторые данные и столбец величин:

In:  df=pd.DataFrame({'first-name':['Jan','Leilani'],'Qty':[2,4]})

Out: Qty    first-name
     2      Jan
     4      Leilani

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

Qty     first-name  position
2       Jan         1
2       Jan         2
4       Leilani     1
4       Leilani     2
4       Leilani     3
4       Leilani     4

Я могу сделать это, используя python так:

l=[]
x=0

for idx in df.index:
    x=0
    for _ in range(df.loc[idx]['Qty']):
        x+=1
        tempSrs=df.loc[idx]
        tempSrs['position']=x
        l.append(tempSrs)

outDf=pd.DataFrame(l)

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

Спасибо

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Здесь используются почти такие же понятия, как и вэнь.

Различия:

  1. loc вместо reindex (тоже самое)
  2. assign вместо = присваивания (assign создает копию)
  3. Передать lambda на assign для встраивания groupby логика

df.loc[df.index.repeat(df.Qty)].assign(
    position=lambda d: d.groupby('first-name').cumcount() + 1
)

   Qty first-name  position
0    2        jan         1
0    2        jan         2
1    4        jay         1
1    4        jay         2
1    4        jay         3
1    4        jay         4

Построить с np.arange

q = df.Qty.values
r = np.arange(q.sum()) - np.append(0, q[:-1]).cumsum().repeat(q) + 1
df.loc[df.index.repeat(q)].assign(position=r)

   Qty first-name  position
0    2        jan         1
0    2        jan         2
1    4        jay         1
1    4        jay         2
1    4        jay         3
1    4        jay         4
0 голосов
/ 09 мая 2018

Вот интуитивно понятный способ использования numpy.repeat и itertools.chain.

Для больших кадров данных это, вероятно, будет более эффективным, чем метод pandorable.

import pandas as pd
import numpy as np
from itertools import chain

df = pd.DataFrame({'first-name':['jan','jay'],'Qty':[2,4]})

lens = df['Qty'].values

res = pd.DataFrame({'Qty': np.repeat(df['Qty'], lens),
                    'first-name': np.repeat(df['first-name'], lens),
                    'Count': list(chain.from_iterable(range(1, i+1) for i in lens))})

print(res)

   Count  Qty first-name
0      1    2        jan
0      2    2        jan
1      1    4        jay
1      2    4        jay
1      3    4        jay
1      4    4        jay
0 голосов
/ 09 мая 2018

С repeat и cumcount

Newdf=df.reindex(df.index.repeat(df.Qty))
Newdf['position']=Newdf.groupby(level=0).cumcount()+1
Newdf
Out[931]: 
   Qty first-name position
0    2        jan        1
0    2        jan        2
1    4        jay        1
1    4        jay        2
1    4        jay        3
1    4        jay        4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...