根据滞后/更改变量创建新列

时间:2019-03-28 06:53:23

标签: python pandas dataframe

已更新

我有一个如下所示的df:

print(df)

           id  rank  a  
date                      
2000-01-01  1   1.0  0  
2000-01-01  2   3.0  0  
2000-01-01  3   2.0  0  
2000-01-01  4   0.0  0  
2000-01-02  1   2.0  0
2000-01-02  2   3.0  0  
2000-01-02  3   2.0  0  
2000-01-02  4   1.0  0
2000-01-03  1   3.0  0 
2000-01-03  2   2.0  0 
2000-01-03  3   1.0  0 
2000-01-03  4   1.0  0   

我想创建一个新变量a,如果rank与上个月相比有所变化,则该变量等于1。例如,在2000-01-01rank是3.0,而在2000-01-02中它变为2.0。我希望此更改与a中的1对应,如果没有更改,请保持为0。我也想对id进行分组。此外,等级在每个期间只能增加1。

预期产量

           id  rank  a  
date                      
2000-01-01  1   1.0  1 
2000-01-01  2   3.0  1  
2000-01-01  3   2.0  1  
2000-01-01  4   0.0  1  
2000-01-02  1   2.0  1
2000-01-02  2   3.0  0  
2000-01-02  3   2.0  0  
2000-01-02  4   1.0  1
2000-01-03  1   3.0  1 
2000-01-03  2   2.0  1 
2000-01-03  3   1.0  1 
2000-01-03  4   1.0  0   

任何帮助都会很棒!

5 个答案:

答案 0 :(得分:4)

Series.diffSeries.abs一起使用,如果可能的话,更像1的地方使用Series.clip

df['a'] = df['rank'].diff().abs().clip(upper=1)

如果差异始终只有1

df['a'] = df['rank'].diff().abs()

如果需要将第一个值设置为0

df['a'] = df['rank'].diff().fillna(0).ne(0).astype(int)

修改后的答案:

df['a1'] = df.groupby('id')['rank'].diff().ne(0).astype(int)
print (df)
          date  id  rank  a  a1
0   2000-01-01   1   1.0  1   1
1   2000-01-01   2   3.0  1   1
2   2000-01-01   3   2.0  1   1
3   2000-01-01   4   0.0  1   1
4   2000-01-02   1   2.0  1   1
5   2000-01-02   2   3.0  0   0
6   2000-01-02   3   2.0  0   0
7   2000-01-02   4   1.0  1   1
8   2000-01-03   1   3.0  1   1
9   2000-01-03   2   2.0  1   1
10  2000-01-03   3   1.0  1   1
11  2000-01-03   4   1.0  0   0

答案 1 :(得分:2)

使用shift

import pandas as pd
df = pd.DataFrame({"rank": [3.0, 2.0, 2.0, 2.0, 1.0]})

df['a'] = (df['rank'] - df['rank'].shift(1)).abs()
print(df)

输出

   rank    a
0   3.0  NaN
1   2.0  1.0
2   2.0  0.0
3   2.0  0.0
4   1.0  1.0

编辑

如果要用空字符串替换NaN

df['a'] = df['a'].fillna('').astype(str)

编辑2

使用np.where,由于上面的代码段将产生实际的差异,因此使用此方法可为您带来1的差异,否则为0:

import pandas as pd
df = pd.DataFrame({"rank": [3.0, 12.0, 2.0, 2.0, 1.0]})

df['a'] = np.where((df['rank'] - df['rank'].shift(1)).abs() > 0, 1, 0)
print(df)

答案 2 :(得分:1)

您可以使用np.select

df0 = df.shift()
cond1 = df0['rank'].isnull()   # to set first row nan
cond2 = df0['rank'] != df['rank']

df['a'] = np.select([cond1,cond2], [0,1], 0)

print(df)

答案 3 :(得分:0)

d['a'] = (d['rank'].shift() == d['rank']).map({True:0, False:1})

请注意,列a的第一个元素是1。不需要时将其删除。
希望对您有帮助。

答案 4 :(得分:0)

这也可以通过使用Series.diff()并将以下一系列布尔值直接转换为整数来完成:

df['a']=df['rank'].diff().eq(-1).astype(int)
相关问题