超人等级 - 由于重复而导致Pandas DataFrame重塑

时间:2017-05-19 22:09:27

标签: python-2.7 pandas dataframe pivot reshape

你喜欢只有超人可以解决的谜题吗?这是证明这种能力的最终测试。

单个公司可能会在不同时间从多家银行获得不同级别的资金(种子,a)。

让我们看看数据,然后看故事以获得更好的画面。

import pandas as pd
data = {'id':[1,2,2,3,4],'company':['alpha','beta','beta','alpha','alpha'],'bank':['z', 'x', 'y', 'z', 'j'], 
    'rd': ['seed', 'seed', 'seed', 'a', 'a'], 'funding': [100, 200, 200, 300, 50],
   'date': ['2006-12-01', '2004-09-01', '2004-09-01', '2007-05-01', '2007-09-01']}
df = pd.DataFrame(data, columns = ['id','company', 'round', 'bank', 'funding', 'date'])
df

收率:

   id  company        rd   bank    funding        date
0   1    alpha      seed      z        100  2006-12-01
1   2     beta      seed      x        200  2004-09-01
2   2     beta      seed      y        200  2004-09-01
3   3    alpha         a      z        300  2007-05-01
4   4    alpha         a      j         50  2007-09-01

期望输出:

   company     bank_seed   funding_seed      date_seed    bank_a  funding_a      date_a 
0    alpha             z            100     2006-12-01     [z,j]        350  2007-09-01
1     beta         [x,y]            200     2004-09-01      None       None        None

正如你所看到的,我不是一个超人,但会尝试解释我的思维过程。

让我们看看公司alpha

2006年底,公司阿尔法首次从银行z获得100美元的种子资金。几个月后,他们的投资者对他们的进展非常满意,因此银行给了他们钱(300美元以上!)。然而,公司阿尔法需要更多的现金,但不得不去一些随机的瑞士银行j来保持活力。银行j不情愿地再给了50美元。好极了!他们现在已经从他们更新的' a'圆形结束于2007年9月。

公司测试版非常新。他们从两家不同的银行获得了总计200美元的资金。但是等等......这里没有什么关于他们的回合' a'。没关系,我们现在就把“无”,稍后再与他们联系。

问题是公司的阿尔法很糟糕并且从瑞士那里得到了钱...... 这是我的非工作代码,它处理了我的一部分数据 - 它在这里不起作用。

import itertools

unique_company = df.company.unique()
df_indexed = df.set_index(['company', 'rd'])
index = pd.MultiIndex.from_tuples(list(itertools.product(unique_company, list(df.rd.unique()))))
reindexed = df_indexed.reindex(index, fill_value=0)

reindexed = reindexed.unstack().applymap(lambda cell: 0 if '1970-01-01' in str(cell) else cell)

working_df = pd.DataFrame(reindexed.iloc[:, 
reindexed.columns.get_level_values(0).isin(['company', 'funding'])].to_records())

如果您知道如何解决部分此问题,请继续将其置于下方。提前谢谢你花时间看看这个! :)

最后,如果您想了解我的代码 的工作方式。然后,这样做,但你失去了这么多有价值的信息......

 df = df.drop_duplicates(subset='id')
 df = df.drop_duplicates(subset='rd')

2 个答案:

答案 0 :(得分:4)

采取预处理步骤,将资金分布在具有相同'id''date'

的记录中
df.funding /= df.groupby(['id', 'date']).funding.transform('count')

然后处理

d1 = df.groupby(['company', 'round']).agg(
    dict(bank=lambda x: tuple(x), funding='sum', date='last')
).unstack().sort_index(1, 1)

d1.columns = d1.columns.to_series().map('{0[0]}_{0[1]}'.format)

d1


           bank funding       date    bank funding       date
round         a       a          a    seed    seed       seed
company                                                      
alpha    (z, j)   350.0 2007-09-01    (z,)   100.0 2006-12-01
beta       None     NaN        NaT  (x, y)   200.0 2004-09-01

答案 1 :(得分:3)

Groupby,aggregate和unstack会让你接近你想要的东西

df.groupby(['company', 'round']).agg({'bank': lambda x: ','.join(x), 'funding': 'sum', 'date': 'max'}).unstack().reset_index()

df.columns = ['_'.join(col).strip() for col in df.columns.values]

你得到了

    company_    bank_a  bank_seed   funding_a   funding_seed  date_a    date_seed
0   alpha       z,j     z           350.0       100.0         2007-09-01 2006-12-01
1   beta        None    x,y         NaN         400.0         None        2004-09-01