Python:按条件删除重复项

时间:2020-07-10 23:04:13

标签: python pandas

我有一些学期开始月份和学期结束月份的数据。

Name   Year   Month   Start
A      1994   05       1
A      1996   04       0
B      1996   04       1
B      1996   12       0
C      1996   12       1
C      1999   02       0

Start列等于1表示该人从本月开始,0表示他/她在本月离开职位。

我需要将此月度数据转换为年度数据,即指定给定年份中处于该职位的人。我的想法是找到在该职位上呆了半年以上的人。也就是说,我要实现:

Year    Name
1994    A
1995    A
1996    B
1997    C
1998    C

我认为我需要根据df['Year']删除重复项。

我可以df_annual = df.drop_duplicates(subset=['Year'])考虑到期限,我认为如果df['Month']<'06'Start == 0df['Month']>'06'和{{1 }}。也就是说,他们在下半年离开,或者在上半年开始任职。

通常,问题归结为如果它们具有相同的Start == 1,则如何选择一行。

有人知道如何在python中执行此操作吗?

2 个答案:

答案 0 :(得分:4)

这很艰难。我选择重新编制索引,以便进入1997年和1998年这样的失踪年份。然后,我使用ffill()填写了Start列,为大量使用的np.where逻辑做准备删除不必要的行。

输入:

df = pd.DataFrame({'Name': {0: 'A', 1: 'A', 2: 'B', 3: 'B', 4: 'C', 5: 'C'},
 'Year': {0: 1994, 1: 1996, 2: 1996, 3: 1996, 4: 1996, 5: 1999},
 'Month': {0: 5, 1: 4, 2: 4, 3: 12, 4: 12, 5: 2},
 'Start': {0: 1, 1: 0, 2: 1, 3: 0, 4: 1, 5: 0}})

代码:

#reindexing to get missing years
df['dt'] = pd.to_datetime(df['Year'], format='%Y')
df = (df.set_index('dt').groupby('Name')
             .apply(lambda d: d.reindex(pd.date_range(min(df.dt),
                                                      max(df.dt),
                                                      freq='YS')))
             .drop('Name', axis=1)
             .reset_index('Name').reset_index())
#specified logic to keep relevant rows and columns
df['Start'] = df['Start'].ffill()
m1 = np.where(~((df['Start'] == df['Start'].shift())
                     & (df['Start'] == 0)
                      & (df['Start'].shift() == 0))
                      | (df['Year'].notnull()),
                     'keep', 'drop')
df = df[m1 == 'keep']
m2 = np.where(((df['Month']< int('06')) & (df['Start'] == 0))
             | ((df['Month']>int('06')) & (df['Start'] == 1)),
                      'drop', 'keep')
df = df[m2 == 'keep']
df['Year'] = df['index'].dt.year
df = df.drop(['index', 'Month', 'Start'], axis=1).reset_index(drop=True)
df

输出:

    Name Year
0   A    1994
1   A    1995
2   B    1996
3   C    1997
4   C    1998

答案 1 :(得分:3)

在第一行中有一点逻辑,当year的开始大于6,而month的结束小于6时,我们确实调整了month。 / p>

# if the month start is greater the 6 you do not want it that year count, for the end month same. 
df.Year=np.where(df.Start==1, (df.Month>=6)+df.Year, df.Year-(df.Month<=6))
s=df.pivot('Name','Start','Year')
s['New']=[range(x, y+1) for x , y in zip(s[1],s[0])]

s=s['New'].explode().drop_duplicates(keep='last')
Name
A    1994
A    1995
B    1996
C    1997
C    1998
Name: New, dtype: object