You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas内置方法求字符串Series或GroupBy对象的中位数

问题:如何在不完整排序的情况下找到字符串列的字典序中位值?

我有一个美国婴儿姓名数据集,其中包含Name列。需要基于姓名的字典序找到该列的中位姓名,但不想通过完全排序整个列的方式实现。尝试使用Pandas内置的median()方法并设置numeric_only=False,但触发错误:TypeError: could not convert string to float: 'Emma'。想知道操作是否有误,或者有没有合适的内置方法?

数据集片段

,Id,Name,Year,Gender,State,Count
11349,11350,Emma,2004,F,AK,62
11350,11351,Madison,2004,F,AK,48
11351,11352,Hannah,2004,F,AK,46
11352,11353,Grace,2004,F,AK,44
11353,11354,Emily,2004,F,AK,41
11354,11355,Abigail,2004,F,AK,37

尝试的代码

import pandas as pd
baby_names = pd.read_csv(
    "Pandas_DataMart\DataMart\06_Stats\US_Baby_Names\US Baby Names.xlsx")

print(baby_names['Name'].median(numeric_only=False))

完整错误信息

Traceback (most recent call last):
File "C:\Users\JohnDoe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\nanops.py", line 720, in nanmedian
values = values.astype("f8")
ValueError: could not convert string to float: 'Emma'

上述异常是以下异常的直接原因:

Traceback (most recent call last):
File "c:\Users\...\BabyNames.py", line 18, in <module>
print(baby_names['Name'].median(numeric_only=False))
File "C:\Users\JohnDoe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\generic.py", line 10802, in median
return NDFrame.median(self, axis, skipna, level, numeric_only, **kwargs)
File "C:\Users\JohnDoe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\generic.py", line 10374, in median
return self._stat_function(
File "C:\Users\JohnDoe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\generic.py", line 10354, in _stat_function
return self._reduce(
File "C:\Users\JohnDoe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\series.py", line 4392, in _reduce
return op(delegate, skipna=skipna, **kwds)
File "C:\Users\JohnDoe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\nanops.py", line 156, in f
result = alt(values, axis=axis, skipna=skipna, **kwds)
File "C:\Users\JohnDoe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\pandas\core\nanops.py", line 723, in nanmedian
raise TypeError(str(err)) from err
TypeError: could not convert string to float: 'Emma'

解答

为什么median()方法不可行?

Pandas的median()方法本质是为数值型数据设计的,即使设置numeric_only=False,其底层逻辑仍然会尝试将数据转换为浮点型进行计算,字符串类型无法完成这个转换,因此触发错误。该方法不支持基于字典序的字符串中位值计算。

高效的替代方案:使用nsmallest()/nlargest()

Pandas的nsmallest(n, column)方法内部使用堆排序算法,无需对整个数据集进行完全排序(时间复杂度为O(n),远优于全排序的O(nlogn)),可以高效找到第n小的元素,正好符合你的需求。

步骤:

  1. 计算数据集Name列的长度,确定中位位置:
    • 如果总长度为奇数,中位位置为len(series) // 2(索引从0开始)
    • 如果总长度为偶数,可选择中间两个元素中的任意一个(比如取第len(series)//2 -1或len(series)//2个)
  2. 使用nsmallest()获取对应位置的元素

示例代码:

import pandas as pd

# 读取正确的CSV文件(修正原代码中xlsx的错误)
baby_names = pd.read_csv("https://raw.githubusercontent.com/guipsamora/pandas_exercises/master/06_Stats/US_Baby_Names/US_Baby_Names_right.csv")

name_series = baby_names['Name']
n = len(name_series)

# 计算中位位置并获取中位姓名
if n % 2 == 1:
    median_pos = n // 2
    median_name = name_series.nsmallest(median_pos + 1).iloc[-1]
else:
    # 偶数长度时取中间第二个元素,可根据需求调整为第一个
    median_pos = n // 2
    median_name = name_series.nsmallest(median_pos + 1).iloc[-1]

print("字典序中位姓名:", median_name)

说明:

  • nsmallest(k)会返回前k个最小的元素(按字典序),取最后一个元素就是第k小的元素
  • 这种方法避免了全排序,性能更优,尤其是在数据集较大时

内容的提问来源于stack exchange,提问作者MJK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 12:12:21