我正在尝试重塑我的数据。乍一看,它听起来像一个转置,但事实并非如此。我尝试过熔化,堆叠/拆散,连接等等。
使用案例
我希望每个唯一个体只有一行,并将所有作业历史记录放在列上。对于客户来说,跨行读取信息比读取列更容易。
以下是数据:
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
答案 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()
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()
对象的 groupby
与dataframe
的对象不同。对于数据框,.apply()
将可调用对象作为其参数,并将该可调用对象应用于对象中的每个列(或行)。传递给该callable的对象是pd.Series
。当您在.apply
上下文中使用dataframe
时,记住这一事实会很有帮助。在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)
这里唯一缺少的是我们想要取消堆叠结果以获得所需的输出。
答案 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