您好我正在处理如下数据框:
yearStart 2014 2015 2016 2017 2018 2019
0 2015 0 150 200 0 0 0
1 2016 0 0 200 140 35 10
2 2017 0 0 0 20 12 12
通常情况下,这是一份包含所有费用的财务报告,在签订合同时开始(专栏开始'年份开始')并持续数年
yearStart Year+0 Year+1 Year+2 Year+3 Year+4 ... Year+N
0 2015 150 200 0 0 0
1 2016 200 140 35 0 0
2 2017 20 12 12 0 0
如何重新整形数据框,以便从合约的第一年开始以相对日期样式存储数据。
我在每一行上尝试了iterrows()并将相关列复制到另一个数据框中,但这需要花费太多时间......
编辑:
好吧,我忘了说在合同的相关期间可能有一年,价值是0,不应该忘记。要考虑的列在yearStart中的日期和结束之间,作为参数给出。输入更像是这样:
0 2015 0 150 200 0 13 0
1 2016 0 0 200 140 35 0 10
2 2017 0 0 0 20 12 0 12
谢谢
答案 0 :(得分:1)
使用带有过滤的apply
创建新行,然后分配新的列名称
df1 = df.apply(lambda x: pd.Series(x[x!=0].values), 1).fillna(0).astype(int)
df1.columns = df.columns.tolist()[:len(df1.columns)]
df1 = df1.reindex(columns=df.columns, fill_value=0)
print (df1)
yearStart 2014 2015 2016 2017 2018 2019
0 2015 150 200 0 0 0 0
1 2016 200 140 35 10 0 0
2 2017 20 12 12 0 0 0
如果可以使用更大的DataFrame,请使用Divakar函数justify_rows
:
def justify_rows(a, side='left'):
mask = a>0
justified_mask = np.sort(mask,1)
if side=='left':
justified_mask = justified_mask[:,::-1]
out = np.zeros_like(a)
out[justified_mask] = a[mask]
return out
df1 = pd.DataFrame(justify_rows(df.values), columns=df.columns, index=df.index)
print (df1)
yearStart 2014 2015 2016 2017 2018 2019
0 2015 150 200 0 0 0 0
1 2016 200 140 35 10 0 0
2 2017 20 12 12 0 0 0
如果想要字符串Years
:
cols = ['yearStart'] + ['Year+{}'.format(x) for x in range(len(df.columns) - 1)]
df1 = pd.DataFrame(justify_rows(df.values), columns=cols, index=df.index)
print (df1)
yearStart Year+0 Year+1 Year+2 Year+3 Year+4 Year+5
0 2015 150 200 0 0 0 0
1 2016 200 140 35 10 0 0
2 2017 20 12 12 0 0 0
编辑:
对于第二个解决方案,需要this solution来选择第一个连续的0
:
def justify_rows(a, side='left'):
mask = a.cumsum(axis=1) != 0
print (mask)
justified_mask = np.sort(mask,1)
print (justified_mask)
if side=='left':
justified_mask = justified_mask[:,::-1]
out = np.zeros_like(a)
out[justified_mask] = a[mask]
print (out)
return out
cols = ['Year+{}'.format(x) for x in range(len(df.columns) - 1)]
df1 = df[['yearStart']].join(pd.DataFrame(justify_rows(df.values[:, 1:]),
columns=cols, index=df.index))
print (df1)
yearStart Year+0 Year+1 Year+2 Year+3 Year+4 Year+5
0 2015 150 200 0 13 0 0
1 2016 200 140 35 0 0 0
2 2017 20 12 0 0 0 0
答案 1 :(得分:1)
df=df.replace({0:np.nan})
df=df.loc[:,df.isnull().sum(0).ne(3)]
选项1:
df.apply(lambda x : (x[x.notnull()].values.tolist()+x[x.isnull()].values.tolist()),1).fillna(0)
出[145]:
yearStart 2015 2016 2017 2018 2019
0 2015.0 150.0 200.0 0.0 0.0 0.0
1 2016.0 200.0 140.0 35.0 10.0 0.0
2 2017.0 20.0 12.0 12.0 0.0 0.0
选项2:
df.apply(lambda x: sorted(x, key=pd.isnull), 1).fillna(0)
Out[145]:
yearStart 2015 2016 2017 2018 2019
0 2015.0 150.0 200.0 0.0 0.0 0.0
1 2016.0 200.0 140.0 35.0 10.0 0.0
2 2017.0 20.0 12.0 12.0 0.0 0.0