如何创建自己的类别类型代码



我有一个在Python中使用的外壳数据帧。其中一根柱子上有"房子";等级";数据,这是基于一个实际的官方县分级系统。这些房屋按3-12的等级进行分级,描述如下:;良好"平均值"优秀";,等等。但是,列中的数据是字符串格式的,数字等级先出现,然后是空格,后面是描述。

因此例如一个条目可以读作">7平均";。(此处为更好的可视化(

我想先从字符串中消除数字,我可以这样做。然后我想把每个字符串条目转换成一个类别类型,我也可以这么做。但是,当我使用.cat.code自动生成类别代码时,有没有办法使用原始的县规模(3-12(作为我的代码?我想我可以使用热编码,但我觉得这看起来很乱,很不专业。

编辑:我只是去掉了描述,保留了数字并转换为int,这很有效。然而,我仍然想看看我最初的问题是否有答案。

无法定义Categorical数据类型的代码。当你试图设置代码时,这可能会引发两种异常:

>>> pd.Categorical.from_codes(...)
ValueError: codes need to be between -1 and len(categories)-1
>>> mycat.codes = [...]
AttributeError: can't set attribute

Categorical数据类型使用-1表示缺失值,使用0表示N索引类别(通常按字典顺序表示字符串值(。

你能做的最好的事情就是创建这样的类别:

data = df['grade'].str.split(' ', 1, expand=True).astype({0: int})
grade = pd.CategoricalDtype(data.drop_duplicates(0).sort_values(0)[1], ordered=True, name='Grade')
df['grade'] = data[1].astype(grade)

输出:

>>> grade
CategoricalDtype(categories=['Low Average', 'Average', 'Good', 'Excellent'], ordered=True)
>>> df['grade']
0    Low Average
1        Average
2           Good
3      Excellent
Name: grade, dtype: category
Categories (4, object): ['Low Average' < 'Average' < 'Good' < 'Excellent']
>>> df['grade'].cat.codes
0    0
1    1
2    2
3    3
dtype: int8

由于您的数据已经具有内在的有序性,我们可以使其有序分类,然后重命名类别:

df.grade = pd.Categorical(df.grade, ordered=True)
df.grade = df.grade.cat.rename_categories(df.grade.cat.categories.str[2:])

给定:

df = pd.DataFrame({'grade':['6 Low Average', '5 Bad', '8 Good', '7 Average', '7 Average']})
print(df.sort_values('grade'))

# Output:
grade
1          5 Bad
0  6 Low Average
3      7 Average
4      7 Average
2         8 Good

操作:

df.grade = pd.Categorical(df.grade, ordered=True)
df.grade = df.grade.cat.rename_categories(df.grade.cat.categories.str[2:])
print(df.sort_values('grade'))
df.sort_values('grade').grade.cat.codes
# Output:
grade
1          Bad
0  Low Average
3      Average
4      Average
2         Good
1    0
0    1
3    2
4    2
2    3
dtype: int8
# If they weren't categorical ordered it'd look like:
#          grade
# 3      Average
# 4      Average
# 1          Bad
# 2         Good
# 0  Low Average

可以这样做:

df = pd.DataFrame({'nr_grade': ['7 Average', '8 Good', '8 Good']})
df[['nr', 'grade']] = df['nr_grade'].str.split(' ', expand=True)
df['grade'] = pd.Categorical(df.grade, categories=df.grade.unique())
df.info()

输出:

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3 entries, 0 to 2
Data columns (total 3 columns):
#   Column    Non-Null Count  Dtype   
---  ------    --------------  -----   
0   nr_grade  3 non-null      object  
1   nr        3 non-null      object  
2   grade     3 non-null      category
dtypes: category(1), object(2)
memory usage: 303.0+ bytes