【问题标题】:Dynamically do a join on pandas dataframes动态地对 pandas 数据框进行连接
【发布时间】:2016-05-27 16:39:02
【问题描述】:

我想过滤列,然后动态连接生成的数据框。我天真的方法是;给定一个数据框,编写一个函数,根据列中的值进行过滤,使其变小然后加入。但我不知道如何动态加入。有更好的方法吗?

data = {'name': ['Jason', 'Molly', 'Jason', 'Jason', 'Molly'],
        'year': [2012, 2012, 2013, 2014, 2014],
        'sale': [41, 24, 31, 32, 31]}

df = pd.DataFrame(data)
print df

def joinDF(df):
    unique_yr = df.year.unique().tolist()  
    i = 1
    for yr in unique_yr:
        df1 = df.loc[df['year'] == yr]
        if len(df.index) != 0:
           #make columns unique then join on name
           df1[['year'+ str(i),'sale'+ str(i), 'name']] = df1[['year','sale','name']]
           i+=1
           print df1

joinDF(df)

   sale name  year
0   41  Jason  2012
1   24  Molly  2012
2   31  Jason  2013
3   32  Jason  2014
4   31  Molly  2014

   sale1 name   year1
0   41   Jason  2012
1   24   Molly  2012

   sale2 name   year2
2   31   Jason  2013

   sale3 name   year3
3   32   Jason  2014
4   31   Molly  2014

执行join,生成的输出数据框应如下所示:

    sale1 name1  year1  sale2   year2  sale3  year3
0   41   Jason  2012   31     2013   32    2014
1   24   Molly  2012   NA     NA     31    2014

【问题讨论】:

  • 不清楚你在问什么。你想要什么数据框作为输出?而age的信息又是从哪里来的?
  • @IanS 对不起,我把它改成了销售,没有年龄。输出应该是所有三个的连接,如图所示

标签: python pandas


【解决方案1】:

factorize可以和pivot_table一起使用,dfyear列排序:

df['groups'] = (pd.factorize(df.year)[0] + 1).astype(str)

df1 = (df.pivot_table(index='name', columns='groups', values=['sale', 'year']))
df1.columns = [''.join(col) for col in df1.columns]
print (df1)
       sale1  sale2  sale3   year1   year2   year3
name                                              
Jason   41.0   31.0   32.0  2012.0  2013.0  2014.0
Molly   24.0    NaN   31.0  2012.0     NaN  2014.0

pivot_table 使用aggfunc,如果重复则默认为aggfunc=np.mean。更好的示例解释是heredocs

【讨论】:

  • 美丽的解决方案@jezrael。谢谢!
  • 如何在数据框中只包含 sale1,而不是 sale1、sale2、sale3?
  • 你认为只有sale1year1 吗?
  • 我不确定,您到底需要什么 - 按年份过滤是print (df[df.year == 2012]),删除其他销售print (df1.drop(['sale2','sale3'], axis=1)),仅过滤销售1 (df1[['sale1']])。如果你需要不同的东西,你能解释更多吗?
【解决方案2】:

如果您绝对需要这种重复的 saleX、nameX 格式的输出,我认为@jezrael 可以做到。

但您可能想改用更简单的pivot,这样使用起来会少很多尴尬。

In [1]: pivot = df.pivot(index='name',columns='year', values='sale')
        print(pivot)
Out[1]: 
year   2012  2013  2014
name                   
Jason  41.0  31.0  32.0
Molly  24.0   NaN  31.0

【讨论】:

  • 是的,但我认为这种格式与想要的 OP 不同。
  • 这正是我开始回答的原因,如果他绝对需要这样的输出,他应该看看你的答案。提出一种可能更健康的替代方案并没有什么坏处
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-22
  • 2013-06-05
  • 2020-05-24
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多