>我有以下数据库:
firm sic identifier name year X Y Z
1078 2834.0 002824100 ABBOTT LABORATORIES 2013 4.347826 5.217391 15.739130
1078 2834.0 002824100 ABBOTT LABORATORIES 2014 4.368421 6.263158 16.684211
112178 2836.0 00339B107 ABGENIX INC 2005 5.222222 3.111111 9.777778
112178 2836.0 00339B107 ABGENIX INC 2006 5.222222 4.111111 10.777778
178855 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 4.000000 0.000000 13.544322
我打算将每个组的年份变量向后延长 5 年。公司、原文如此、标识符和名称列将需要复制到新行。但是,X、Y 和 Z 列将是 NAN。
预期结果:
firm sic identifier name year X Y Z
1078 2834.0 002824100 ABBOTT LABORATORIES 2008 NAN NAN NAN
1078 2834.0 002824100 ABBOTT LABORATORIES 2009 NAN NAN NAN
1078 2834.0 002824100 ABBOTT LABORATORIES 2010 NAN NAN NAN
1078 2834.0 002824100 ABBOTT LABORATORIES 2011 NAN NAN NAN
1078 2834.0 002824100 ABBOTT LABORATORIES 2012 NAN NAN NAN
1078 2834.0 002824100 ABBOTT LABORATORIES 2013 4.347826 5.217391 15.739130
1078 2834.0 002824100 ABBOTT LABORATORIES 2014 4.368421 6.263158 16.684211
112178 2836.0 00339B107 ABGENIX INC 2000 NAN NAN NAN
112178 2836.0 00339B107 ABGENIX INC 2001 NAN NAN NAN
112178 2836.0 00339B107 ABGENIX INC 2002 NAN NAN NAN
112178 2836.0 00339B107 ABGENIX INC 2003 NAN NAN NAN
112178 2836.0 00339B107 ABGENIX INC 2004 NAN NAN NAN
112178 2836.0 00339B107 ABGENIX INC 2005 4.454545 3.181818 11.000000
112178 2836.0 00339B107 ABGENIX INC 2006 4.222222 4.000000 13.555556
178855 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 NAN NAN NAN
178855 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 NAN NAN NAN
178855 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 NAN NAN NAN
178855 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 NAN NAN NAN
178855 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 NAN NAN NAN
178855 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 4.000000 0.000000 13.544322
如果你有一些如何在python中实现的想法,请与我分享。
提前谢谢。
您可以使用index.repeat
和merge
f = df.groupby('firm').first()
d = f.loc[f.index.repeat(5)]
d.assign(year=d.year+np.tile(np.arange(-5, 0), len(f)),
X=np.nan,
Y=np.nan,
Z=np.nan)
.merge(df.set_index('firm'), how='outer')
.sort_values(['identifier', 'year'])
sic identifier name year X Y Z
0 2834.0 002824100 ABBOTT LABORATORIES 2008 NaN NaN NaN
1 2834.0 002824100 ABBOTT LABORATORIES 2009 NaN NaN NaN
2 2834.0 002824100 ABBOTT LABORATORIES 2010 NaN NaN NaN
3 2834.0 002824100 ABBOTT LABORATORIES 2011 NaN NaN NaN
4 2834.0 002824100 ABBOTT LABORATORIES 2012 NaN NaN NaN
15 2834.0 002824100 ABBOTT LABORATORIES 2013 4.347826 5.217391 15.739130
16 2834.0 002824100 ABBOTT LABORATORIES 2014 4.368421 6.263158 16.684211
5 2836.0 00339B107 ABGENIX INC 2000 NaN NaN NaN
6 2836.0 00339B107 ABGENIX INC 2001 NaN NaN NaN
7 2836.0 00339B107 ABGENIX INC 2002 NaN NaN NaN
8 2836.0 00339B107 ABGENIX INC 2003 NaN NaN NaN
9 2836.0 00339B107 ABGENIX INC 2004 NaN NaN NaN
17 2836.0 00339B107 ABGENIX INC 2005 5.222222 3.111111 9.777778
18 2836.0 00339B107 ABGENIX INC 2006 5.222222 4.111111 10.777778
10 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2002 NaN NaN NaN
11 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2003 NaN NaN NaN
12 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2004 NaN NaN NaN
13 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2005 NaN NaN NaN
14 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2006 NaN NaN NaN
19 2836.0 00383Y102 ABRAXIS BIOSCIENCE INC 2007 4.000000 0.000000 13.544322
IIUC 您可以使用groupby
explode
和merge
,如以下代码所示
import pandas as pd
# Sanity check
df["year"] = df["year"].astype(int)
# groupby + explode
cols = ["firm","sic", "identifier", "name", "year"]
grp = df.groupby(cols[:-1])
.agg({"year":{"min","max"}})
.apply(lambda x: np.arange(x["year"]["min"]-5,
x["year"]["max"]+1),
axis=1)
.reset_index(name="year")
.explode("year")
.reset_index(drop=True)
grp["year"] = grp["year"].astype(int)
# merge
df = pd.merge(grp,df, on=cols, how="left")
您可以将索引设置为年份值,并按特定日期范围重新编制索引。 在这个例子中,我为每个组追溯了 7 年。
在:
df = df.set_index(pd.to_datetime(df['year'], format='%Y'))
df = df.groupby('identifier', as_index=False)
.apply(lambda x: x.reindex(pd.date_range(start=x.index.max(), periods=7,freq='-1AS-JAN')))
.reset_index(level=0, drop=True)
df.year = df.index.year
df[['firm','sic', 'identifier','name']] = df[['firm','sic', 'identifier','name']].fillna(method='ffill')
df.sort_values(['identifier','year']).reset_index(drop=True)
外:
| | firm | sic | identifier | name | year | X | Y | Z |
|----|----------|--------|------------|----------------------|------|----------|----------|-----------|
| 0 | 1078.0 | 2834.0 | 002824100 | ABBOTTLABORATORIES | 2008 | NaN | NaN | NaN |
| 1 | 1078.0 | 2834.0 | 002824100 | ABBOTTLABORATORIES | 2009 | NaN | NaN | NaN |
| 2 | 1078.0 | 2834.0 | 002824100 | ABBOTTLABORATORIES | 2010 | NaN | NaN | NaN |
| 3 | 1078.0 | 2834.0 | 002824100 | ABBOTTLABORATORIES | 2011 | NaN | NaN | NaN |
| 4 | 1078.0 | 2834.0 | 002824100 | ABBOTTLABORATORIES | 2012 | NaN | NaN | NaN |
| 5 | 1078.0 | 2834.0 | 002824100 | ABBOTTLABORATORIES | 2013 | 4.347826 | 5.217391 | 15.739130 |
| 6 | 1078.0 | 2834.0 | 002824100 | ABBOTTLABORATORIES | 2014 | 4.368421 | 6.263158 | 16.684211 |
| 7 | 112178.0 | 2836.0 | 00339B107 | ABGENIXINC | 2000 | NaN | NaN | NaN |
| 8 | 112178.0 | 2836.0 | 00339B107 | ABGENIXINC | 2001 | NaN | NaN | NaN |
| 9 | 112178.0 | 2836.0 | 00339B107 | ABGENIXINC | 2002 | NaN | NaN | NaN |
| 10 | 112178.0 | 2836.0 | 00339B107 | ABGENIXINC | 2003 | NaN | NaN | NaN |
| 11 | 112178.0 | 2836.0 | 00339B107 | ABGENIXINC | 2004 | NaN | NaN | NaN |
| 12 | 112178.0 | 2836.0 | 00339B107 | ABGENIXINC | 2005 | 5.222222 | 3.111111 | 9.777778 |
| 13 | 112178.0 | 2836.0 | 00339B107 | ABGENIXINC | 2006 | 5.222222 | 4.111111 | 10.777778 |
| 14 | 178855.0 | 2836.0 | 00383Y102 | ABRAXISBIOSCIENCEINC | 2001 | NaN | NaN | NaN |
| 15 | 178855.0 | 2836.0 | 00383Y102 | ABRAXISBIOSCIENCEINC | 2002 | NaN | NaN | NaN |
| 16 | 178855.0 | 2836.0 | 00383Y102 | ABRAXISBIOSCIENCEINC | 2003 | NaN | NaN | NaN |
| 17 | 178855.0 | 2836.0 | 00383Y102 | ABRAXISBIOSCIENCEINC | 2004 | NaN | NaN | NaN |
| 18 | 178855.0 | 2836.0 | 00383Y102 | ABRAXISBIOSCIENCEINC | 2005 | NaN | NaN | NaN |
| 19 | 178855.0 | 2836.0 | 00383Y102 | ABRAXISBIOSCIENCEINC | 2006 | NaN | NaN | NaN |
| 20 | 178855.0 | 2836.0 | 00383Y102 | ABRAXISBIOSCIENCEINC | 2007 | 4.000000 | 0.000000 | 13.544322 |