假设我们有一个结构如下的数据框:
df = pd.DataFrame({
'Year':[2017, 2019, 2018, 2017, 2017, 2017],
'B':[4,5,4,5,5,4],
'C':[0,0,0,0,0,7],
'D':[0,1,3,5,7,1],
'E':[5,3,6,9,2,4],
总体思路是将每一行移动一次,与“年份”列中的值相对应,2017年是基准年,应在(年份-2017年)单元格上将每一行右移,并用零(0),例如:
df = pd.DataFrame({
'Year':[2017, 2019, 2018, 2017, 2017, 2017],
'B':[4,0,0,5,5,4],
'C':[0,0,4,0,0,7],
'D':[0,5,0,5,7,1],
'E':[5,0,3,9,2,4],
'F':[0,1,6,0,0,0],
'G':[0,3,0,0,0,0],
})
ps:实际上,我们接下来需要对结果行进行成对求和,以便每一列的“年”都相同
仅当我们对0和2行求和时才适用。然后应该是1和3,依此类推
答案 0 :(得分:1)
如果默认情况下在熊猫中使用shift
,则最后一列会丢失。因此有必要先添加由缺失值填充的新列-列数取决于非2017年值的差异。
df = df.set_index('Year')
diff = np.setdiff1d(df.index.dropna().unique(), [2017]).astype(int)
print (diff)
[2018 2019]
df = df.assign(**{f'new{x}':np.nan for x in range(max(diff-2017))})
然后,您可以循环使用shift
并按索引中的年份按DataFrame.loc
进行过滤:
for y in diff:
df.loc[y, :] = df.astype(float).shift(y - 2017, axis=1).loc[y, :]
最后一次替换丢失的值,转换为整数并将索引转换为列:
df = df.fillna(0).astype(int).reset_index()
print (df)
Year B C D E new0 new1
0 2017 4 0 0 5 0 0
1 2019 0 0 5 0 1 3
2 2018 0 4 0 3 6 0
3 2017 5 0 5 9 0 0
4 2017 5 0 7 2 0 0
5 2017 4 7 1 4 0 0
编辑:
另一列的解决方案:
df = pd.DataFrame({
'new':list('abcdef'),
'Year':[2017, 2019, 2018, 2017, 2017, 2017],
'B':[4,5,4,5,5,4],
'C':[0,0,0,0,0,7],
'D':[0,1,3,5,7,1],
'E':[5,3,6,9,2,4]})
print (df)
new Year B C D E
0 a 2017 4 0 0 5
1 b 2019 5 0 1 3
2 c 2018 4 0 3 6
3 d 2017 5 0 5 9
4 e 2017 5 0 7 2
5 f 2017 4 7 1 4
df = df.set_index(['new','Year'])
diff = np.setdiff1d(df.index.get_level_values('Year').dropna().unique(), [2017]).astype(int)
print (diff)
[2018 2019]
df1 = pd.DataFrame(index=df.index, columns=['new{}'.format(x) for x in range(max(diff-2017))])
df = pd.concat([df, df1], axis=1)
print (df)
B C D E new0 new1
new Year
a 2017 4 0 0 5 NaN NaN
b 2019 5 0 1 3 NaN NaN
c 2018 4 0 3 6 NaN NaN
d 2017 5 0 5 9 NaN NaN
e 2017 5 0 7 2 NaN NaN
f 2017 4 7 1 4 NaN NaN
for y in diff:
idx = pd.IndexSlice
df.loc[idx[:, y], :] = df.astype(float).shift(y - 2017, axis=1).loc[idx[:, y], :]
df = df.fillna(0).astype(int).reset_index()
print (df)
new Year B C D E new0 new1
0 a 2017 4 0 0 5 0 0
1 b 2019 0 0 5 0 1 3
2 c 2018 0 4 0 3 6 0
3 d 2017 5 0 5 9 0 0
4 e 2017 5 0 7 2 0 0
5 f 2017 4 7 1 4 0 0
答案 1 :(得分:1)
我以编程方式创建了从第一个df帧到最后一个df帧的操作步骤。我这样做是因为看来您可能正在寻找以编程方式进行该操作的方法,这可能会对最终结果有所帮助。有了一点了解,我可能可以使此过程更容易:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'Year':[2017, 2019, 2018, 2017, 2017, 2017],
'B':[4,5,4,5,5,4],
'C':[0,0,0,0,0,7],
'D':[0,1,3,5,7,1],
'E':[5,3,6,9,2,4],})
df.insert(column='F',loc=len(df)-1,value=np.zeros(len(df),dtype=int))
df.insert(column='G',loc=len(df)-1,value=np.zeros(len(df),dtype=int))
df1 = df.T
cols =df1.iloc[0]
df1.columns = cols
df1.drop('Year', inplace=True)
df1.iloc[0:, [1]] = np.roll(df1.iloc[0:, [1]], shift=2)
df1.iloc[0:, [2]] = np.roll(df1.iloc[0:, [2]], shift=1)
df = df1.T.reset_index()
res = df.iloc[2] + df.iloc[0]
df = df.append(res, ignore_index=True)
df['Year'][6]= 'res'
输出:
Year B C D E G F
0 2017 4 0 0 5 0 0
1 2019 0 0 5 0 1 3
2 2018 0 4 0 3 6 0
3 2017 5 0 5 9 0 0
4 2017 5 0 7 2 0 0
5 2017 4 7 1 4 0 0
6 res 4 4 0 8 6 0