Pandas:将组中的第一个值转换为 np.nan

Pandas: convert first value in group to np.nan

我有以下数据框:

df = pd.DataFrame({'series1':['A','A','A','A','B','B','B','C','C','C','C'],
                   'series2':[0,1,10,99,-9,9,0,10,20,10,10]})
   series1  series2
0        A      0.0
1        A      1.0
2        A     10.0
3        A     99.0
4        B     -9.0
5        B      9.0
6        B      0.0
7        C     10.0
8        C     20.0
9        C     10.0
10       C     10.0

我想要的:

df2 = pd.DataFrame({'series1':['A','A','A','A','B','B','B','C','C','C','C'],
                   'series2':[np.nan,1,10,99,np.nan,9,0,np.nan,20,10,10]})
   series1  series2
0        A      NaN
1        A      1.0
2        A     10.0
3        A     99.0
4        B      NaN
5        B      9.0
6        B      0.0
7        C      NaN
8        C     20.0
9        C     10.0
10       C     10.0

我觉得这可以通过使用 Pandas .groupby 函数来完成:

df.groupby('series1').first()
         series2
series1         
A              0
B             -9
C             10

这给了我想要转换为 NaN 的观察结果,但我想不出一种方法可以轻松地在原始 DataFrame 中替换它。

这只是一个简单的示例,我正在处理的实际数据框有 >8,000,000 个观察值。

您想通过向下移动并与自身比较来定位 series1 中的不连续点:

df.loc[df['series1'].shift() != df['series1'], 'series2'] = np.nan

可能有更巧妙的方法来做到这一点,但每个组中的第一个元素是该组中的第 0 个元素,并且 cumcount 对每个组中的元素进行编号。所以:

In [19]: df.loc[df.groupby('series1').cumcount() == 0, 'series2'] = np.nan

In [20]: df
Out[20]: 
   series1  series2
0        A      NaN
1        A      1.0
2        A     10.0
3        A     99.0
4        B      NaN
5        B      9.0
6        B      0.0
7        C      NaN
8        C     20.0
9        C     10.0
10       C     10.0

通过移动列的另一个选项:

df['series2'] = df.groupby('series1').series2.transform(lambda x: x.shift(-1).shift())

df
#  series1  series2
#0       A      NaN
#1       A      1.0
#2       A     10.0
#3       A     99.0
#4       B      NaN
#5       B      9.0
#6       B      0.0
#7       C      NaN
#8       C     20.0
#9       C     10.0
#10      C     10.0

或者您可以使用 headfirstnth 都通过索引切片返回相同的结果。

    df.loc[df.groupby('series1',as_index=False).head(1).index,'series2'] = np.nan
    #df.loc[df.groupby('series1',as_index=False).first().index,'series2'] = np.nan
    #df.loc[df.groupby('series1',as_index=False).nth(1).index,'series2'] = np.nan