Mam Pandas DataFrame, w której respondenci odpowiadają na to samo pytanie na wielu kontach sprzedaży. Moje dane wejściowe Dataframe mają następujący format

df = pd.DataFrame({"Sales_Acc1":[100,300],
              "Sales_Acc2":[200,500],
              "Time_Acc1":[2,5],
              "Time_acc2":[6,9],
              "Acc_Number_acc1":[1001,1005],
              "Acc_Number_acc2":[1009,1010]},
             index=["John","Dave"])
df
>>> Sales_Acc1  Sales_Acc2  Time_Acc1   Time_acc2   Acc_Number_acc1 Acc_Number_acc2
John    100     200          2          6           1001            1009
Dave    300     500          5          9           1005            1010

Chcę to zmienić, aby każde konto miało własny wiersz. Mój pożądany koniec Dataframe wyglądałby tak:

df
>>> AccountNumber   Rep   Sales   Time 
     1001           John  100     2
     1005           John  300     6
     1009           Dave  200     5
     1010           Dave  500     9

Próbowałem używać zarówno stopu, jak i obrotu, ale nie mogę tego rozgryźć. Doceniam każdą pomoc.

1
Victor Nogueira 7 kwiecień 2020, 21:40

2 odpowiedzi

Najlepsza odpowiedź

To jest wide_to_long Problem biorąc pod uwagę, że Twoje kolumny mają format 'stub_SomeSuffix'. Ponieważ masz kilka niespójnych przypadków, obniżymy wszystko. Musimy również usunąć nazwy z index, ponieważ wide_to_long wymaga kolumn.

df.columns = df.columns.str.lower()

df = (pd.wide_to_long(df.rename_axis('Rep').reset_index(),    # Use Rep as index
                      i='Rep',                                # index of output
                      j='will_drop',                          # Suffix labels  
                      stubnames=['sales', 'acc_number', 'time'],
                      sep='_', 
                      suffix='.*') 
        .reset_index()
        .drop(columns='will_drop'))

#    Rep  sales  acc_number  time
#0  John    100        1001     2
#1  Dave    300        1005     5
#2  John    200        1009     6
#3  Dave    500        1010     9

Jeśli nie jesteś fanem niekończących się argumentów wymaganych przez wide_to_long, możemy zamiast tego utworzyć proste MultiIndex na kolumnach, a to jest stack. Ponownie, z powodu niespójnej wielkości liter, wszystkie kolumny są całkowicie małe.

df.columns = pd.MultiIndex.from_arrays(zip(*df.columns.str.lower().str.rsplit('_', n=1)))
#     sales      time      acc_number      
#      acc1 acc2 acc1 acc2       acc1  acc2
#John   100  200    2    6       1001  1009
#Dave   300  500    5    9       1005  1010

df.stack(-1).reset_index(-1, drop=True)
#      acc_number  sales  time
#John        1001    100     2
#John        1009    200     6
#Dave        1005    300     5
#Dave        1010    500     9
3
ALollz 7 kwiecień 2020, 20:07
df1=df[['Sales_Acc1','Time_Acc1','Acc_Number_acc1']]
df2=df[['Sales_Acc2','Time_acc2','Acc_Number_acc2']]
df1.columns=['Sales_Acc','Time_Acc','Acc_Number']
df2.columns=['Sales_Acc','Time_Acc','Acc_Number']
df3 = df1.append(df2)
df3.index.names = ['Rep']

Moje rozwiązanie jest tak proste i zadziałałoby w tym przypadku, w zasadzie umieszczamy kolumny w różnych wierszach.

Najpierw wybierz odpowiednie kolumny, a następnie zmień nazwy kolumn i dołącz je do innych, aby uzyskać ostateczny wynik.

Oto pełny kod:

import pandas as pd
df = pd.DataFrame({"Sales_Acc1":[100,300],
              "Sales_Acc2":[200,500],
              "Time_Acc1":[2,5],
              "Time_acc2":[6,9],
              "Acc_Number_acc1":[1001,1005],
              "Acc_Number_acc2":[1009,1010]},
             index=["John","Dave"])
df1=df[['Sales_Acc1','Time_Acc1','Acc_Number_acc1']]
df2=df[['Sales_Acc2','Time_acc2','Acc_Number_acc2']]
df1.columns=['Sales_Acc','Time_Acc','Acc_Number']
df2.columns=['Sales_Acc','Time_Acc','Acc_Number']
df3 = df1.append(df2)
df3.index.names = ['Rep']
df3.head()

Wynik:

enter image description here

2
user27286 7 kwiecień 2020, 22:14