Pandas 创建一个完美的面板数据,根据条件追加空行
Pandas creating a perfect panel data, appending empty rows based on conditions
我正在寻找一种在满足两个条件的情况下将空行附加到数据框的方法。条件是,如果在特定年份未找到索引 ID,代码将添加一个空行,其中包含索引 'ID' 和年份,但其他列为空。最终目的是创建一个完美的面板数据集,其中每个观察值代表 7 次(基于年份),尽管可能有来自某些观察值的数据,例如1 次或 3 次(这不是恒定的,而是不时变化的)。除了索引 'ID' 和 year.
之外,这些缺失的数据行将是空的
这是我的数据框 all_data 当前的示例:
ID Year Data1 Data2
345 2010 3 2
345 2011 1 4
345 2012 5 2
345 2013 3 1
345 2014 3 1
345 2015 3 1
345 2016 3 1
123 2010 1 1
123 2012 0 2
123 2016 0 2
这是我正在寻找的示例。
ID Year Data1 Data2
345 2010 3 2
345 2011 1 4
345 2012 5 2
345 2013 3 1
345 2014 3 1
345 2015 3 1
345 2016 3 1
123 2010 1 1
123 2011
123 2012 0 2
123 2013
123 2014
123 2015
123 2016 0 2
我有超过 200 个观察值和 20 个数据列,因此手动执行此操作会花费太多时间。这是我尝试过的方法,但没有用。它 returns 相同的数据框并且不添加任何空行。 'missing' 是一个列表,其中包含可以从 all_data 数据帧中找到的每个唯一 ID。
missing = ['345', '123']
sub_dfs = []
for year in [ 2010, 2011, 2012, 2013, 2014, 2015, 2016 ]:
sub_df = all_data.loc[ all_data[ 'Year' ] == year ].copy()
if( year == 2010):
sub_df.set_index( 'ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2011):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2012):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2013):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2014):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2015):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2016):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
sub_dfs.append(sub_df)
new_data = pd.concat(sub_dfs)
提前感谢您的帮助!
将 ID
的 reindex
by Multiindex
created by MultiIndex.from_product
by all unique
值与 np.arange
最小和最大 year
s:
mux = pd.MultiIndex.from_product([df['ID'].unique(),
np.arange(df['Year'].min(), df['Year'].max() + 1)],
names=['ID','Year'])
df = df.set_index(['ID','Year']).reindex(mux).reset_index()
print (df)
ID Year Data1 Data2
0 345 2010 3.0 2.0
1 345 2011 1.0 4.0
2 345 2012 5.0 2.0
3 345 2013 3.0 1.0
4 345 2014 3.0 1.0
5 345 2015 3.0 1.0
6 345 2016 3.0 1.0
7 123 2010 1.0 1.0
8 123 2011 NaN NaN
9 123 2012 0.0 2.0
10 123 2013 NaN NaN
11 123 2014 NaN NaN
12 123 2015 NaN NaN
13 123 2016 0.0 2.0
jezrael 总是更快,但我想在这里学习 pandas,所以这是我的尝试 ;)
我正在使用重采样方法:您想通过将数据重新映射到年度开始 ('AS') 间隔
来填充空白
首先将'Year'列转换为pandas日期时间并设置为索引
df.Year = pd.to_datetime(df.Year, format="%Y")
df = df.set_index('Year')
然后我分别处理每个唯一 ID 并创建一个新的输出 DataFrame
IDs = df.ID.unique()
newDf = pd.DataFrame()
处理循环
for ID in IDs:
# resample to annual start (although end would also be OK)
temp = df[df.ID==ID].resample('AS').sum()
# fill in the blanks, now 0, with the wanted data
temp[temp.ID==0] = pd.DataFrame({'ID':ID, 'Data1':'', 'Data2':''},
index=temp[temp.ID==0].index)
# concat this new data with the output frame
newDf = pd.concat([newDf, temp])
最后通过删除索引并将日期时间转换回字符串来清理输出
newDf = newDf.reset_index()
newDf.Year = newDf.Year.dt.strftime('%Y')
结果:
Year ID Data1 Data2
0 2010 345 3 2
1 2011 345 1 4
2 2012 345 5 2
3 2013 345 3 1
4 2014 345 3 1
5 2015 345 3 1
6 2016 345 3 1
7 2010 123 1 1
8 2011 123
9 2012 123 0 2
10 2013 123
11 2014 123
12 2015 123
13 2016 123 0 2
我正在寻找一种在满足两个条件的情况下将空行附加到数据框的方法。条件是,如果在特定年份未找到索引 ID,代码将添加一个空行,其中包含索引 'ID' 和年份,但其他列为空。最终目的是创建一个完美的面板数据集,其中每个观察值代表 7 次(基于年份),尽管可能有来自某些观察值的数据,例如1 次或 3 次(这不是恒定的,而是不时变化的)。除了索引 'ID' 和 year.
之外,这些缺失的数据行将是空的这是我的数据框 all_data 当前的示例:
ID Year Data1 Data2
345 2010 3 2
345 2011 1 4
345 2012 5 2
345 2013 3 1
345 2014 3 1
345 2015 3 1
345 2016 3 1
123 2010 1 1
123 2012 0 2
123 2016 0 2
这是我正在寻找的示例。
ID Year Data1 Data2
345 2010 3 2
345 2011 1 4
345 2012 5 2
345 2013 3 1
345 2014 3 1
345 2015 3 1
345 2016 3 1
123 2010 1 1
123 2011
123 2012 0 2
123 2013
123 2014
123 2015
123 2016 0 2
我有超过 200 个观察值和 20 个数据列,因此手动执行此操作会花费太多时间。这是我尝试过的方法,但没有用。它 returns 相同的数据框并且不添加任何空行。 'missing' 是一个列表,其中包含可以从 all_data 数据帧中找到的每个唯一 ID。
missing = ['345', '123']
sub_dfs = []
for year in [ 2010, 2011, 2012, 2013, 2014, 2015, 2016 ]:
sub_df = all_data.loc[ all_data[ 'Year' ] == year ].copy()
if( year == 2010):
sub_df.set_index( 'ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2011):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2012):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2013):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2014):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2015):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
if (year == 2016):
sub_df.set_index('ID', inplace=True)
sub_df.reindex(sub_df.index.union(missing))
sub_dfs.append(sub_df)
new_data = pd.concat(sub_dfs)
提前感谢您的帮助!
将 ID
的 reindex
by Multiindex
created by MultiIndex.from_product
by all unique
值与 np.arange
最小和最大 year
s:
mux = pd.MultiIndex.from_product([df['ID'].unique(),
np.arange(df['Year'].min(), df['Year'].max() + 1)],
names=['ID','Year'])
df = df.set_index(['ID','Year']).reindex(mux).reset_index()
print (df)
ID Year Data1 Data2
0 345 2010 3.0 2.0
1 345 2011 1.0 4.0
2 345 2012 5.0 2.0
3 345 2013 3.0 1.0
4 345 2014 3.0 1.0
5 345 2015 3.0 1.0
6 345 2016 3.0 1.0
7 123 2010 1.0 1.0
8 123 2011 NaN NaN
9 123 2012 0.0 2.0
10 123 2013 NaN NaN
11 123 2014 NaN NaN
12 123 2015 NaN NaN
13 123 2016 0.0 2.0
jezrael 总是更快,但我想在这里学习 pandas,所以这是我的尝试 ;)
我正在使用重采样方法:您想通过将数据重新映射到年度开始 ('AS') 间隔
来填充空白首先将'Year'列转换为pandas日期时间并设置为索引
df.Year = pd.to_datetime(df.Year, format="%Y")
df = df.set_index('Year')
然后我分别处理每个唯一 ID 并创建一个新的输出 DataFrame
IDs = df.ID.unique()
newDf = pd.DataFrame()
处理循环
for ID in IDs:
# resample to annual start (although end would also be OK)
temp = df[df.ID==ID].resample('AS').sum()
# fill in the blanks, now 0, with the wanted data
temp[temp.ID==0] = pd.DataFrame({'ID':ID, 'Data1':'', 'Data2':''},
index=temp[temp.ID==0].index)
# concat this new data with the output frame
newDf = pd.concat([newDf, temp])
最后通过删除索引并将日期时间转换回字符串来清理输出
newDf = newDf.reset_index()
newDf.Year = newDf.Year.dt.strftime('%Y')
结果:
Year ID Data1 Data2
0 2010 345 3 2
1 2011 345 1 4
2 2012 345 5 2
3 2013 345 3 1
4 2014 345 3 1
5 2015 345 3 1
6 2016 345 3 1
7 2010 123 1 1
8 2011 123
9 2012 123 0 2
10 2013 123
11 2014 123
12 2015 123
13 2016 123 0 2