在Python中,如何获取pandas系列的最小值或最大值?

116

我有一个pandas系列 series 。如果我想要获得逐元素的floor或ceiling,是否有内置的方法或者我必须编写函数并使用apply?我问这个问题是因为数据很大,所以我非常重视效率。同时,这个问题还没有关于Pandas软件包的解答。

5个回答

150

您可以使用NumPy的内置方法来完成此操作:np.ceil(series)np.floor(series)

两种方法都返回一个Series对象(而不是数组),因此会保留索引信息。


6
我该如何像在 Pandas 的 Series 上使用 round() 一样链接它? - iamyojimbo
这个可以运行:dataframe["new_series"] = np.ceil(dataframe[series].round(0)) - Dave Sottimano
2
@iamyojimbo,如果你想链式调用方法,请使用pipe()df['column'].pipe(np.ceil) - renan-eccel

37

我是楼主,但我尝试了这个方法并且它起作用了:

np.floor(series)

23

更新:这个答案是错误的,请不要这样做。

说明:在大多数情况下,使用Series.apply()与本地矢量化NumPy函数是没有意义的,因为它将在Python循环中运行Numpy函数,导致性能大大降低。你最好直接使用np.floor(series),正如其他答案所建议的那样。

例如,您可以使用NumPy的floor来处理一个dataframe

floored_data = data.apply(np.floor)

我现在无法测试,但实际可行的解决方案可能不远了。


如果您使用raw=True参数,那么df.apply函数的性能将会有很大提升。 - Raisin
apply函数不是矢量化实现,因此它会非常慢。您可以直接对数据框调用np.floor。 - Péter Szilvási

19

使用pd.Series.clip,可以通过clip(lower=x)clip(upper=x)设置最小值或最大值:

s = pd.Series([-1, 0, -5, 3])
    
print(s.clip(lower=0))
# 0    0
# 1    0
# 2    0
# 3    3
# dtype: int64
    
print(s.clip(upper=0))
# 0   -1
# 1    0
# 2   -5
# 3    0
# dtype: int64

pd.Series.clip 允许进行广义功能,例如同时应用和地板天花板限制,例如 s.clip(-1, 1)

注意: 此答案最初提到的是已在 pandas 1.0.0 中移除clip_lower / clip_upper.


10
我可以看出提及 clip 等函数是有一定关联的,但是剪裁一个值与寻找该值的下限/上限是非常不同的操作... - Alex Riley
@AlexRiley,收到;我提及这点的原因是存在一些情况,上限和下限是来自外部输入的变量,你可能希望(例如)使用s.clip(-1, np.inf)s.clip(-np.inf, 1)来无缝处理这些情况。 - jpp
我对OP的问题表述感到困惑,不太清楚他们想要做什么(包括OP自己的回答)。除非我漏掉了什么,否则如果你有s = pd.Series([3.1, 2.2, 5.6]),似乎没有办法仅使用clip来计算与np.floor(s)相同的结果。 (这并不是贬低你的答案,你的答案写得很好,提供了有用的信息 - 我只是在重新阅读问题时感到困惑。) - Alex Riley
3
啊,现在重新阅读这个问题也让我感到困惑。我是通过谷歌搜索“如何将 Pandas series 拉平”来找到这个问题的。所以我会留下这个答案,供其他通过同样途径找到这个有些含糊不清的问题的人参考! - jpp

7

置顶答案已经是最快的了。这里我提供了一些使用纯pandas实现天花板和地板操作的替代方法,并将其与numpy方法进行了比较。

series = pd.Series(np.random.normal(100,20,1000000))

地板

%timeit np.floor(series) # 1.65 ms ± 18.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit series.astype(int) # 2.2 ms ± 131 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit (series-0.5).round(0) # 3.1 ms ± 47 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit round(series-0.5,0) # 2.83 ms ± 60.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

为什么 astype int 能够起作用?因为在 Python 中,转换为整数时,它总是向下取整。
天花板(Ceil)
%timeit np.ceil(series) # 1.67 ms ± 21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit (series+0.5).round(0) # 3.15 ms ± 46.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit round(series+0.5,0) # 2.99 ms ± 103 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

所以,只需使用NumPy函数即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接