从行到列重塑pandas数据帧

时间:2016-07-31 07:37:37

标签: python pandas dataframe reshape pandas-groupby

我正在尝试重塑我的数据。乍一看,它听起来像一个转置,但事实并非如此。我尝试过熔化,堆叠/拆散,连接等等。

使用案例

我希望每个唯一个体只有一行,并将所有作业历史记录放在列上。对于客户来说,跨行读取信息比读取列更容易。

以下是数据:

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

这就是我想要它的样子: Desired Output Table

enter image description here

6 个答案:

答案 0 :(得分:7)

.T

中的

groupby

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

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

enter image description here

解释

groupby返回一个对象,其中包含有关如何对原始系列或数据框进行分组的信息。我们可以先将groupby分配给变量(我经常这样做),而不是执行df2.groupby('Name')某个变量({1}},而不是gb

gb = df2.groupby('Name')

在此对象gb上,我们可以调用.mean()来获取每个组的平均值。或.last()获取每个组的最后一个元素(行)。或者.transform(lambda x: (x - x.mean()) / x.std())在每个组中进行zscore转换。如果您希望在没有预定义功能的组中执行某些操作,则仍有.apply()

.apply()对象的

groupbydataframe的对象不同。对于数据框,.apply()将可调用对象作为其参数,并将该可调用对象应用于对象中的每个列(或行)。传递给该callable的对象是pd.Series。当您在.apply上下文中使用dataframe时,记住这一事实会很有帮助。在groupby对象的上下文中,传递给callable参数的对象是数据帧。实际上,该数据框是groupby指定的组之一。

当我写这些函数以传递给groupby.apply时,我通常将参数定义为df以反映它是一个数据帧。

好的,我们有:

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

这会为每个'Name'生成一个子数据帧,并将该子数据帧传递给函数tgrp。然后groupby对象重新组合所有已经通过tgrp函数重新组合的组。

看起来像这样。

enter image description here

我把OP的原始尝试简单地转移到了内心。但我必须先做一些事情。我完成了:

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

enter image description here

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

enter image description here

手动合并(不含groupby):

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

enter image description here

哇!现在那很难看。显然[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])

enter image description here

那好多了。但现在我们正在进入groupby打算处理的领土。所以让它来处理它。

返回

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

这里唯一缺少的是我们想要取消堆叠结果以获得所需的输出。

enter image description here

答案 1 :(得分:2)

假设您从拆散开始:

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

这给出了

 transform.eulerAngles = Vector3.Lerp(gos[5].transform.eulerAngles, targetAngles, smooth * Time.deltaTime);

答案 2 :(得分:1)

这是一种可行的解决方法。在这里,我首先创建一个正确形式的字典,并基于新字典创建一个DataFrame:

//Init table element (in this case by tag name but better chose by id or Name)
IWebElement tableElement = driver.FindElement(By.TagName("table"));

//Init TR elements from table we found into list
IList<IWebElement> trCollection = tableElement.FindElements(By.TagName("tr"));
//define TD elements collection.
IList<IWebElement> tdCollection;

//loop every row in the table and init the columns to list
foreach(IWebElement element in trCollection)
{
   tdCollection = element.FindElements(By.TagName("td"));

   //now in the List you have all the columns of the row
   string column1 = tdCollection[0].Text;
   string column2 = tdCollection[1].Text;
   ...
}

答案 3 :(得分:1)

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

答案 4 :(得分:0)

这不是您要求的,但这是一种打印数据框的方法:

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    

答案 5 :(得分:0)

潜入@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