作者 |B. Chen
编译 |VK
起源 |Towards Data Science
Pandas DataFrame 有一个内置办法 sort_values(),能够依据给定的变量对值进行排序。该办法自身应用起来相当简略,然而它不适用于自定义排序,例如,
- t 恤尺寸:XS、S、M、L 和 XL
- 月份:一月、二月、三月、四月等
- 星期几:周一、周二、周三、周四、周五、周六和周日。
在本文中,咱们将理解如何对 Pandas DataFrame 进行自定义排序。
请查看我的 Github repo 以获取源代码:https://github.com/BindiChen/…
问题
假如咱们有一个对于服装店的数据集:
df = pd.DataFrame({'cloth_id': [1001, 1002, 1003, 1004, 1005, 1006],
'size': ['S', 'XL', 'M', 'XS', 'L', 'S'],
})
咱们能够看到,每一块布料都有一个尺寸值,数据应该按以下程序排序:
- XS 代表特大号
- S 代表小号
- M 代表中号
- L 代表大号
- XL 为特大号
然而,当调用 sort_values(‘size’)时,将失去以下输入。
输入不是咱们想要的,但它在技术上是正确的。实际上,sort_values()是按数字程序对数值数据排序,对对象数据按字母程序排序。
以下是两种常见的解决方案:
- 为自定义排序创立新列
- 应用 CategoricalDtype 将数据强制转换为具备有序性的类别类型
为自定义排序创立新列
在这个解决方案中,须要一个映射数据帧来示意一个自定义排序,而后依据映射创立一个新的列,最初咱们能够按新列对数据进行排序。让咱们通过一个例子来看看这是如何工作的。
首先,让咱们创立一个映射数据帧来示意自定义排序。
df_mapping = pd.DataFrame({'size': ['XS', 'S', 'M', 'L', 'XL'],
})
sort_mapping = df_mapping.reset_index().set_index('size')
之后,应用 sort_mapping 中的映射值创立一个新的列 size_num。
df['size_num'] = df['size'].map(sort_mapping['index'])
最初,按新的列大小对值进行排序。
df.sort_values('size_num')
这当然是咱们的工作。但它创立了一个备用列,在解决大型数据集时效率可能会升高。
咱们能够应用 CategoricalDtype 更无效地解决这个问题。
应用 CategoricalDtype 将数据强制转换为具备有序性的类别类型
CategoricalDtype 是具备类别和程序的分类数据的类型[1]。它对于创立自定义排序十分有用[2]。让咱们通过一个例子来看看这是如何工作的。
首先,让咱们导入 CategoricalDtype。
from pandas.api.types import CategoricalDtype
而后,创立一个自定义类别类型 cat_size_order
- 第一个参数设置为 [‘XS’、’S’、’M’、’L’、’XL’] 作为尺寸的惟一值。
- 第二个参数 ordered=True,将此变量视为有序。
cat_size_order = CategoricalDtype(['XS', 'S', 'M', 'L', 'XL'],
ordered=True
)
而后,调用 astype(cat_size_order)将大小数据强制转换为自定义类别类型。通过运行 df[‘size’],咱们能够看到 size 列曾经被转换为一个类别类型,其程序为[XS<S<M<L<XL]。
>>> df['size'] = df['size'].astype(cat_size_order)
>>> df['size']
0 S
1 XL
2 M
3 XS
4 L
5 S
Name: size, dtype: category
Categories (5, object): [XS < S < M < L < XL]
最初,咱们能够调用雷同的办法对值进行排序。
df.sort_values('size')
这样成果更好。让咱们来看看原理是什么。
应用 cat 的 codes 属性拜访
当初 size 列曾经被转换为 category 类型,咱们能够应用.cat 拜访器以查看分类属性。在幕后,它应用 codes 属性来示意有序变量的大小。
让咱们创立一个新的列代码,这样咱们能够并排比拟大小和代码值。
df['codes'] = df['size'].cat.codes
df
咱们能够看到 XS、S、M、L 和 XL 的代码别离为 0、1、2、3、4 和 5。codes 是类别理论值。通过运行 df.info(),咱们能够看到实际上是 int8。
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 cloth_id 6 non-null int64
1 size 6 non-null category
2 codes 6 non-null int8
dtypes: category(1), int64(1), int8(1)
memory usage: 388.0 bytes
按多个变量排序
接下来,让咱们把事件变得更简单一点。这里,咱们将按多个变量对数据帧进行排序。
df = pd.DataFrame({'order_id': [1001, 1002, 1003, 1004, 1005, 1006, 1007],
'customer_id': [10, 12, 12, 12, 10, 10, 10],
'month': ['Feb', 'Jan', 'Jan', 'Feb', 'Feb', 'Jan', 'Feb'],
'day_of_week': ['Mon', 'Wed', 'Sun', 'Tue', 'Sat', 'Mon', 'Thu'],
})
相似地,让咱们创立两个自定义类别类型 cat_day_of_week 和 cat_month,并将它们传递给 astype()。
cat_day_of_week = CategoricalDtype(['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
ordered=True
)
cat_month = CategoricalDtype(['Jan', 'Feb', 'Mar', 'Apr'],
ordered=True,
)
df['day_of_week'] = df['day_of_week'].astype(cat_day_of_week)
df['month'] = df['month'].astype(cat_month)
要按多个变量排序,咱们只须要传递一个列表来代替 sort_values()。例如,按 month 和day_of_week排序。
df.sort_values(['month', 'day_of_week'])
按 ustomer_id,month 和day_of_week 排序。
df.sort_values(['customer_id', 'month', 'day_of_week'])
就这样,谢谢你的浏览。
请在我的 Github 上导出笔记本以获取源代码:https://github.com/BindiChen/…
参考援用
- [1] Pandas.CategoricalDtype API(https://pandas.pydata.org/pan…
- [2] Pandas Categorical CategoricalDtype tutorial (https://pandas.pydata.org/pan…
原文链接:https://towardsdatascience.co…
欢送关注磐创 AI 博客站:
http://panchuang.net/
sklearn 机器学习中文官网文档:
http://sklearn123.com/
欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/