【问题标题】:Encode character columns as ordinal but keep numeric columns the same将字符列编码为序数,但保持数字列相同
【发布时间】:2019-04-17 15:42:16
【问题描述】:

我有一个如下数据框:

test = {"viral": "pos", "Status": "positive", "Age": 59, "score": 5}
test2 = {"viral": "neg"}
df = pd.DataFrame.from_dict([test, test2])

我想将字符列(病毒、状态)编码为序数,但不考虑数值。所需的输出是具有相同列名的 numpy 数组。

如果我使用 sklearn 中的 OrdinalEncoder,它不会处理 NaN 值。即使没有 NaN 值,它仍然会对数字列进行序数编码。我想在字符列中用 0 填充 NaN 值,但在数字列中保留 NaN。

最简单的方法是什么?

所需的输出(在 numpy 数组中):

    Age    Status  score viral
0  59.0         1    5.0     1
1   NaN         0    NaN     0

谢谢! 杰克

编辑:当使用enc=OrdinalEncoder() 时,我还想要从编码值到原始值的映射,例如{i: dict(enumerate(v)) for i, v in enumerate(enc.categories_)}(请参阅Vectorize 2D character array column-wise

【问题讨论】:

  • 你是怎么知道pospositive都映射到1的?或者这只是一个巧合,即不是一个要求?
  • @jpp 不是要求 :) 只要我可以将原始值映射回最终编码值,数字的映射方式并不重要。

标签: python pandas numpy scikit-learn


【解决方案1】:

使用LabelEncoder

enc = sklearn.preprocessing.LabelEncoder()

mask = df.dtypes.eq(np.object)
df.loc[:, mask] = df.loc[:, mask].astype(str).apply(enc.fit_transform)

为了能够inverse_transform,您可以创建使用defaultdictLabelEncoderskey 是您的选择。我建议使用列名:直观且简单

from collections import defaultdict
enc = defaultdict(sklearn.preprocessing.LabelEncoder)

mask = df.dtypes.eq(np.object)
df.loc[:, mask] = df.loc[:, mask].astype(str).apply(lambda s: enc[s.name].fit_transform(s))

    Status  viral
0   1       1
1   0       0

inverse_transform

df.loc[:, mask].apply(lambda s: enc[s.name].inverse_transform(s))

    Status      viral
0   positive    pos
1   NaN         neg

【讨论】:

  • 我意识到我应该早点指定这个(我将这个作为编辑添加到问题中)但是是否可以获得编码值到原始值的映射?
【解决方案2】:

更新,当存在 NaN 时,它会将代码分类为 -1 ,如果您需要 NaN,您可以使用 replace 转换回来

df=pd.DataFrame([test,test2])
df.dtypes
Out[152]:
Age       float64
Status     object
score     float64
viral      object
dtype: object
listc=df.columns[df.dtypes=='object']

for x in listc:
    df[x]=df[x].astype('category').cat.codes

df
Out[156]: 
    Age  Status  score  viral
0  59.0       0    5.0      1
1   NaN      -1    NaN      0

【讨论】:

  • 我希望它是可扩展的,不总是只是 pos 或 neg,而是任何字符值。考虑另一种可能值为“蓝色”、“绿色”、“黄色”的列颜色。同样,这不是预期用途,因此我们将不胜感激提供可扩展的解决方案。
  • 谢谢你的downvote,你想留下理由吗?
  • @JackArnestad 谢谢,有没有一种简单的方法可以将数字映射到初始值?使用enc=OrdinalEncoder() 时可能类似于{i: dict(enumerate(v)) for i, v in enumerate(enc.categories_)}(参见stackoverflow.com/questions/53142301/…)。再次感谢!
  • listc = df.select_dtypes(['object']) 可能被认为是惯用的:)
猜你喜欢
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 1970-01-01
  • 2021-05-14
  • 2022-11-16
  • 1970-01-01
  • 2020-04-11
  • 1970-01-01
相关资源
最近更新 更多