如何按 python 中的因子级别对 pandas 数据框中的行重新排序?
How to reorder rows in pandas dataframe by factor level in python?
我创建了一个小型数据集来比较每杯大小的咖啡饮料价格。
当我旋转数据集时,输出会自动按字母顺序对索引('Size' 列)重新排序。
有没有办法为不同的大小分配一个数值级别(例如小 = 0,中 = 1,大 = 2)并以此方式重新排列行?
我知道这可以在 R 中使用 forcats 库完成(例如使用 fct_relevel),但我不知道如何在 python 中完成。我宁愿保留使用 numpy 和 pandas.
的解决方案
data = {'Item': np.repeat(['Latte', 'Americano', 'Cappuccino'], 3),
'Size': ['Small', 'Medium', 'Large']*3,
'Price': [2.25, 2.60, 2.85, 1.95, 2.25, 2.45, 2.65, 2.95, 3.25]
}
df = pd.DataFrame(data, columns = ['Item', 'Size', 'Price'])
df = pd.pivot_table(df, index = ['Size'], columns = 'Item')
df
# Price
# Item Americano Cappuccino Latte
# Size
# Large 2.45 3.25 2.85
# Medium 2.25 2.95 2.60
# Small 1.95 2.65 2.25
您可以将 Categorical
类型与 ordered=True
一起使用:
df.index = pd.Categorical(df.index,
categories=['Small', 'Medium', 'Large'],
ordered=True)
df = df.sort_index()
输出:
Price
Item Americano Cappuccino Latte
Small 1.95 2.65 2.25
Medium 2.25 2.95 2.60
Large 2.45 3.25 2.85
您可以通过以下方式访问代码:
>>> df.index.codes
array([0, 1, 2], dtype=int8)
如果这是一个系列:
>>> series.cat.codes
一个选项是在旋转之前创建分类;对于这种情况,我使用 pyjanitor
中的 encode_categorical
,主要是为了方便:
# pip install pyjanitor
import pandas as pd
import janitor
(df
.encode_categorical(Size = (None, 'appearance'))
.pivot_table(index='Size', columns='Item')
)
Price
Item Americano Cappuccino Latte
Size
Small 1.95 2.65 2.25
Medium 2.25 2.95 2.60
Large 2.45 3.25 2.85
这样一来,您就不必费心排序了,因为旋转会隐式地进行排序。您可以跳过 pyjanitor,只坚持使用 Pandas:
(df
.astype({'Size': pd.CategoricalDtype(categories = ['Small', 'Medium', 'Large'],
ordered = True)})
.pivot_table(index='Size', columns='Item')
)
Price
Item Americano Cappuccino Latte
Size
Small 1.95 2.65 2.25
Medium 2.25 2.95 2.60
Large 2.45 3.25 2.85
第一种方式:
pivot_table
函数根据索引对行进行排序。
因此,在 pivot_table 函数中应用索引时最好使用 lambda 函数。
这样,您就不需要任何进一步的排序步骤(更耗时)或任何第三方库。
df = pd.pivot_table(df, index = (lambda row: 0 if df.loc[row,'Size']=="Small" else 1 if df.loc[row,'Size']=="Medium" else 2),
columns = 'Item')
Price
Item Americano Cappuccino Latte
0 1.95 2.65 2.25
1 2.25 2.95 2.60
2 2.45 3.25 2.85
第二种方式:
您也可以使用自己的代码,然后重命名和排序新创建的 table:
df = pd.DataFrame(data, columns = ['Item', 'Size', 'Price'])
df = pd.pivot_table(df, index = ['Size'], columns = 'Item')
# rename:
df = df.rename(index= lambda x: 0 if x=="Small" else 1 if x=="Medium" else 2)
#sort:
df = df.sort_index(ascending = True)
Price
Item Americano Cappuccino Latte
0 1.95 2.65 2.25
1 2.25 2.95 2.60
2 2.45 3.25 2.85
我创建了一个小型数据集来比较每杯大小的咖啡饮料价格。
当我旋转数据集时,输出会自动按字母顺序对索引('Size' 列)重新排序。
有没有办法为不同的大小分配一个数值级别(例如小 = 0,中 = 1,大 = 2)并以此方式重新排列行?
我知道这可以在 R 中使用 forcats 库完成(例如使用 fct_relevel),但我不知道如何在 python 中完成。我宁愿保留使用 numpy 和 pandas.
的解决方案data = {'Item': np.repeat(['Latte', 'Americano', 'Cappuccino'], 3),
'Size': ['Small', 'Medium', 'Large']*3,
'Price': [2.25, 2.60, 2.85, 1.95, 2.25, 2.45, 2.65, 2.95, 3.25]
}
df = pd.DataFrame(data, columns = ['Item', 'Size', 'Price'])
df = pd.pivot_table(df, index = ['Size'], columns = 'Item')
df
# Price
# Item Americano Cappuccino Latte
# Size
# Large 2.45 3.25 2.85
# Medium 2.25 2.95 2.60
# Small 1.95 2.65 2.25
您可以将 Categorical
类型与 ordered=True
一起使用:
df.index = pd.Categorical(df.index,
categories=['Small', 'Medium', 'Large'],
ordered=True)
df = df.sort_index()
输出:
Price
Item Americano Cappuccino Latte
Small 1.95 2.65 2.25
Medium 2.25 2.95 2.60
Large 2.45 3.25 2.85
您可以通过以下方式访问代码:
>>> df.index.codes
array([0, 1, 2], dtype=int8)
如果这是一个系列:
>>> series.cat.codes
一个选项是在旋转之前创建分类;对于这种情况,我使用 pyjanitor
中的 encode_categorical
,主要是为了方便:
# pip install pyjanitor
import pandas as pd
import janitor
(df
.encode_categorical(Size = (None, 'appearance'))
.pivot_table(index='Size', columns='Item')
)
Price
Item Americano Cappuccino Latte
Size
Small 1.95 2.65 2.25
Medium 2.25 2.95 2.60
Large 2.45 3.25 2.85
这样一来,您就不必费心排序了,因为旋转会隐式地进行排序。您可以跳过 pyjanitor,只坚持使用 Pandas:
(df
.astype({'Size': pd.CategoricalDtype(categories = ['Small', 'Medium', 'Large'],
ordered = True)})
.pivot_table(index='Size', columns='Item')
)
Price
Item Americano Cappuccino Latte
Size
Small 1.95 2.65 2.25
Medium 2.25 2.95 2.60
Large 2.45 3.25 2.85
第一种方式:
pivot_table
函数根据索引对行进行排序。
因此,在 pivot_table 函数中应用索引时最好使用 lambda 函数。
这样,您就不需要任何进一步的排序步骤(更耗时)或任何第三方库。
df = pd.pivot_table(df, index = (lambda row: 0 if df.loc[row,'Size']=="Small" else 1 if df.loc[row,'Size']=="Medium" else 2),
columns = 'Item')
Price
Item Americano Cappuccino Latte
0 1.95 2.65 2.25
1 2.25 2.95 2.60
2 2.45 3.25 2.85
第二种方式:
您也可以使用自己的代码,然后重命名和排序新创建的 table:
df = pd.DataFrame(data, columns = ['Item', 'Size', 'Price'])
df = pd.pivot_table(df, index = ['Size'], columns = 'Item')
# rename:
df = df.rename(index= lambda x: 0 if x=="Small" else 1 if x=="Medium" else 2)
#sort:
df = df.sort_index(ascending = True)
Price
Item Americano Cappuccino Latte
0 1.95 2.65 2.25
1 2.25 2.95 2.60
2 2.45 3.25 2.85