簡體   English   中英

從行到列重塑pandas數據幀

[英]Reshape pandas dataframe from rows to columns

我正在嘗試重塑我的數據。 乍一看,它聽起來像一個轉置,但事實並非如此。 我嘗試過融化,堆疊/取消堆疊,連接等。

用例

我希望每個唯一個體只有一行,並將所有作業歷史記錄放在列上。 對於客戶端,可以更容易地跨行讀取信息而不是讀取列。

這是數據:

import pandas as pd
import numpy as np

data1 = {'Name': ["Joe", "Joe", "Joe","Jane","Jane"],
        'Job': ["Analyst","Manager","Director","Analyst","Manager"],
        'Job Eff Date': ["1/1/2015","1/1/2016","7/1/2016","1/1/2015","1/1/2016"]}
df2 = pd.DataFrame(data1, columns=['Name', 'Job', 'Job Eff Date'])

df2

這就是我想要它的樣子: 所需的輸出表

在此輸入圖像描述

.Tgroupby

def tgrp(df):
    df = df.drop('Name', axis=1)
    return df.reset_index(drop=True).T

df2.groupby('Name').apply(tgrp).unstack()

在此輸入圖像描述


說明

groupby返回一個對象,該對象包含有關如何對原始系列或數據幀進行分組的信息。 我們可以先將df2.groupby('Name')分配給變量(我經常這樣做),而不是使用某種類型的后續動作執行groupby ,比如說gb

gb = df2.groupby('Name')

在這個對象gb我們可以調用.mean()來獲得每個組的平均值。 .last()獲取每個組的最后一個元素(行)。 .transform(lambda x: (x - x.mean()) / x.std())在每個組中進行zscore轉換。 如果您想要在沒有預定義功能的組中執行某些操作,則仍然存在.apply()

groupby對象的.apply()dataframe不同.apply() 對於數據幀, .apply()將可調用對象作為其參數,並將該可調用對象應用於對象中的每個列(或行)。 傳遞給該callable的對象是pd.Series 當您在dataframe .apply上下文中使用.apply時,記住這一事實是有幫助的。 groupby對象的上下文中,傳遞給callable參數的對象是一個數據幀。 實際上,該數據幀是groupby指定的組之一。

當我編寫這樣的函數以傳遞給groupby.apply ,我通常將參數定義為df以反映它是一個數據幀。

好的,我們有:

df2.groupby('Name').apply(tgrp)

這會為每個'Name'生成一個子數據幀,並將該子數據幀傳遞給函數tgrp 然后groupby對象將已經通過tgrp函數的所有這些組重新組合在一起。

它看起來像這樣。

在此輸入圖像描述

我把OP最初的嘗試簡單地轉移到了心上。 但我必須先做一些事情。 我完成了:

df2[df2.Name == 'Jane'].T

在此輸入圖像描述

df2[df2.Name == 'Joe'].T

在此輸入圖像描述

手動組合這些(沒有groupby ):

pd.concat([df2[df2.Name == 'Jane'].T, df2[df2.Name == 'Joe'].T])

在此輸入圖像描述

哇! 現在那很難看。 顯然, [0, 1, 2]的索引值不與[3, 4] 所以讓我們重置一下。

pd.concat([df2[df2.Name == 'Jane'].reset_index(drop=True).T,
           df2[df2.Name == 'Joe'].reset_index(drop=True).T])

在此輸入圖像描述

那好多了。 但是,現在我們正在進入境內groupby旨在處理。 所以讓它來處理它。

回到

df2.groupby('Name').apply(tgrp)

這里唯一缺少的是我們想要取消堆疊結果以獲得所需的輸出。

在此輸入圖像描述

假設您從拆散開始:

df2 = df2.set_index(['Name', 'Job']).unstack()
>>> df2
    Job Eff Date
Job Analyst Director    Manager
Name            
Jane    1/1/2015    None    1/1/2016
Joe 1/1/2015    7/1/2016    1/1/2016
In [29]:

df2

現在,為了簡化操作,請將多索引展平:

df2.columns = df2.columns.get_level_values(1)
>>> df2
Job Analyst Director    Manager
Name            
Jane    1/1/2015    None    1/1/2016
Joe 1/1/2015    7/1/2016    1/1/2016

現在,只需操縱列:

cols = []
for i, c in enumerate(df2.columns):
    col = 'Job %d' % i
    df2[col] = c
    cols.append(col)
    col = 'Eff Date %d' % i
    df2[col] = df2[c]
    cols.append(col)
>>> df2[cols]
Job Job 0   Eff Date 0  Job 1   Eff Date 1  Job 2   Eff Date 2
Name                        
Jane    Analyst 1/1/2015    Director    None    Manager 1/1/2016
Joe Analyst 1/1/2015    Director    7/1/2016    Manager 1/1/2016

編輯

簡從來就不是導演(唉)。 以上代碼表明Jane在None日期成為董事。 要更改結果,以便指定Jane在None日期變為None (這是一個品味問題),請替換

df2[col] = c

通過

df2[col] = [None if d is None else c for d in df2[c]]

這給了

Job Job 0   Eff Date 0  Job 1   Eff Date 1  Job 2   Eff Date 2
Name                        
Jane    Analyst 1/1/2015    None    None    Manager 1/1/2016
Joe Analyst 1/1/2015    Director    7/1/2016    Manager 1/1/2016

這是一個可能的解決方法。 在這里,我首先創建一個正確形式的字典,並基於新字典創建一個DataFrame:

df = pd.DataFrame(data1)

dic = {}

for name, jobs in df.groupby('Name').groups.iteritems():
    if not dic:
        dic['Name'] = []
    dic['Name'].append(name)
    for j, job in enumerate(jobs, 1):
        jobstr = 'Job {0}'.format(j)
        jobeffdatestr = 'Job Eff Date {0}'.format(j)
        if jobstr not in dic:
            dic[jobstr] = ['']*(len(dic['Name'])-1)
            dic[jobeffdatestr] = ['']*(len(dic['Name'])-1)
        dic[jobstr].append(df['Job'].ix[job])
        dic[jobeffdatestr].append(df['Job Eff Date'].ix[job])

df2 = pd.DataFrame(dic).set_index('Name')

##         Job 1    Job 2     Job 3 Job Eff Date 1 Job Eff Date 2 Job Eff Date 3
## Name                                                                         
## Jane  Analyst  Manager                 1/1/2015       1/1/2016               
## Joe   Analyst  Manager  Director       1/1/2015       1/1/2016       7/1/2016
g = df2.groupby('Name').groups
names = list(g.keys())
data2 = {'Name': names}
cols = ['Name']
temp1 = [g[y] for y in names]
job_str = 'Job'
job_date_str = 'Job Eff Date'
for i in range(max([len(x) for x in g.values()])):
    temp = [x[i] if len(x) > i else '' for x in temp1]
    job_str_curr = job_str + str(i+1)
    job_date_curr = job_date_str + str(i + 1)
    data2[job_str + str(i+1)] = df2[job_str].ix[temp].values
    data2[job_date_str + str(i+1)] = df2[job_date_str].ix[temp].values
    cols.extend([job_str_curr, job_date_curr])

df3 = pd.DataFrame(data2, columns=cols)
df3 = df3.fillna('')
print(df3)
  Name Job1 Job Eff Date1 Job2 Job Eff Date2 Job3 Job Eff Date3 0 Jane Analyst 1/1/2015 Manager 1/1/2016 1 Joe Analyst 1/1/2015 Manager 1/1/2016 Director 7/1/2016 

這不是您要求的,但這是一種打印數據框的方法:

df = pd.DataFrame(data1)
for name, jobs in df.groupby('Name').groups.iteritems():
    print '{0:<15}'.format(name),
    for job in jobs:
        print '{0:<15}{1:<15}'.format(df['Job'].ix[job], df['Job Eff Date'].ix[job]),
    print

## Jane            Analyst        1/1/2015        Manager        1/1/2016       
## Joe             Analyst        1/1/2015        Manager        1/1/2016        Director       7/1/2016    

潛入@piRSquared答案....

def tgrp(df):
    df  = df.drop('Name', axis=1)
    print df, '\n'   
    out =  df.reset_index(drop=True)   
    print out, '\n'
    out.T 
    print out.T, '\n\n'
    return  out.T

dfxx = df2.groupby('Name').apply(tgrp).unstack()
dfxx

以上的輸出。 為什么熊貓會重復第一組呢? 這是一個錯誤嗎?

       Job Job Eff Date
3  Analyst     1/1/2015
4  Manager     1/1/2016 

       Job Job Eff Date
0  Analyst     1/1/2015
1  Manager     1/1/2016 

                     0         1
Job            Analyst   Manager
Job Eff Date  1/1/2015  1/1/2016 


       Job Job Eff Date
3  Analyst     1/1/2015
4  Manager     1/1/2016 

       Job Job Eff Date
0  Analyst     1/1/2015
1  Manager     1/1/2016 

                     0         1
Job            Analyst   Manager
Job Eff Date  1/1/2015  1/1/2016 


        Job Job Eff Date
0   Analyst     1/1/2015
1   Manager     1/1/2016
2  Director     7/1/2016 

        Job Job Eff Date
0   Analyst     1/1/2015
1   Manager     1/1/2016
2  Director     7/1/2016 

                     0         1         2
Job            Analyst   Manager  Director
Job Eff Date  1/1/2015  1/1/2016  7/1/2016 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM