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
或者您可以使用 head
、first
或 nth
都通过索引切片返回相同的结果。
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
我有以下数据框:
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
或者您可以使用 head
、first
或 nth
都通过索引切片返回相同的结果。
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