Python 移位局部数据帧';s行,具体取决于特定单元格中的值
假设我们有一个数据帧,其结构如下:Python 移位局部数据帧';s行,具体取决于特定单元格中的值,python,pandas,dataframe,Python,Pandas,Dataframe,假设我们有一个数据帧,其结构如下: 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年)单
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)填充,如:
ps:实际上,我们需要对一些结果行进行成对求和,以便每列的“年份”相同
当我们求0和2行的和时,这只是第一步。那么它应该是1和3,依此类推
因此,也许有一些pandas功能可以帮助您在不预先移位的情况下完成此任务…如果默认情况下在pandas中使用
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
,并在索引中按年份过滤:
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帧的步骤。我这样做是因为您可能正在寻找如何以编程方式实现这一点,并且它可能有助于最终结果。稍微了解一下,我可能会使这个过程更容易:
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
_实际上,我们需要对一些结果行进行成对求和,这样每个列的“年”都是相同的,您能更具体一些吗?什么决定了哪些行应该求和?您的最终数据帧看起来如何?lilke?@Alexander Cécile很抱歉让您困惑。因此,我们必须对第0行和第2行、第1行和第3行求和,依此类推。我们需要改变它,因为例如,单元格df.iloc[0,1]与2017年相关,但df.iloc[1,1]与2019年相关,因此我们无法对其求和。我仍然不确定我是否理解。你是如何处理存在多次出现的年份这一事实的?@Alexander Cécile你的意思是“2017年”?我们不需要更改“年”列中包含“2017”的行。
实际上,完整df中的“年”在[2017,2035]范围内。
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
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