转换熊猫数据框中的分类数据
Posted
技术标签:
【中文标题】转换熊猫数据框中的分类数据【英文标题】:Convert categorical data in pandas dataframe 【发布时间】:2015-11-07 18:52:19 【问题描述】:我有一个包含此类数据的数据框(列太多):
col1 int64
col2 int64
col3 category
col4 category
col5 category
列看起来像这样:
Name: col3, dtype: category
Categories (8, object): [B, C, E, G, H, N, S, W]
我想将列中的所有值转换为整数,如下所示:
[1, 2, 3, 4, 5, 6, 7, 8]
我通过这个解决了一列的问题:
dataframe['c'] = pandas.Categorical.from_array(dataframe.col3).codes
现在我的数据框中有两列——旧的col3
和新的c
,需要删除旧的列。
这是不好的做法。这是可行的,但在我的数据框中有很多列,我不想手动执行。
这个pythonic是怎么做到的?
【问题讨论】:
【参考方案1】:只需使用手动匹配:
dict = 'Non-Travel':0, 'Travel_Rarely':1, 'Travel_Frequently':2
df['BusinessTravel'] = df['BusinessTravel'].apply(lambda x: dict.get(x))
【讨论】:
【参考方案2】:categorical_columns =['sex','class','deck','alone']
for column in categorical_columns:
df[column] = pd.factorize(df[column])[0]
Factorize 会将列中每个唯一的分类数据变成一个特定的数字(从 0 到无穷大)。
【讨论】:
【参考方案3】:你可以使用.replace
如下:
df['col3']=df['col3'].replace(['B', 'C', 'E', 'G', 'H', 'N', 'S', 'W'],[1,2,3,4,5,6,7,8])
或.map
:
df['col3']=df['col3'].map(1: 'B', 2: 'C', 3: 'E', 4:'G', 5:'H', 6:'N', 7:'S', 8:'W')
【讨论】:
【参考方案4】:要将 Dataframe 中的所有列转换为数值数据:
df2 = df2.apply(lambda x: pd.factorize(x)[0])
【讨论】:
【参考方案5】:这里的答案似乎已经过时了。 Pandas 现在有一个factorize()
函数,你可以创建如下类别:
df.col.factorize()
函数签名:
pandas.factorize(values, sort=False, na_sentinel=- 1, size_hint=None)
【讨论】:
【参考方案6】:你可以像下面这样减少代码:
f = pd.DataFrame('col1':[1,2,3,4,5], 'col2':list('abcab'),'col3':list('ababb'))
f['col1'] =f['col1'].astype('category').cat.codes
f['col2'] =f['col2'].astype('category').cat.codes
f['col3'] =f['col3'].astype('category').cat.codes
f
【讨论】:
【参考方案7】:将分类变量转换为虚拟/指示变量的最简单方法之一是使用 pandas 提供的get_dummies。
例如,我们有数据,其中sex
是一个分类值(男性和女性)
您需要将其转换为虚拟/指标,这是如何做到的。
tranning_data = pd.read_csv("../titanic/train.csv")
features = ["Age", "Sex", ] //here sex is catagorical value
X_train = pd.get_dummies(tranning_data[features])
print(X_train)
Age Sex_female Sex_male
20 0 1
33 1 0
40 1 0
22 1 0
54 0 1
【讨论】:
这正是我正在寻找的pythonic方式!谢谢!【参考方案8】:我所做的是,我replace
价值观。
像这样-
df['col'].replace(to_replace=['category_1', 'category_2', 'category_3'], value=[1, 2, 3], inplace=True)
这样,如果col
列有分类值,它们将被数值替换。
【讨论】:
【参考方案9】:对于某一列,如果不关心排序,就用这个
df['col1_num'] = df['col1'].apply(lambda x: np.where(df['col1'].unique()==x)[0][0])
如果您关心排序,请将它们指定为列表并使用它
df['col1_num'] = df['col1'].apply(lambda x: ['first', 'second', 'third'].index(x))
【讨论】:
【参考方案10】:为了转换数据集data的C列中的分类数据,我们需要执行以下操作:
from sklearn.preprocessing import LabelEncoder
labelencoder= LabelEncoder() #initializing an object of class LabelEncoder
data['C'] = labelencoder.fit_transform(data['C']) #fitting and transforming the desired categorical column.
【讨论】:
【参考方案11】:这里需要转换多个列。所以,我使用的一种方法是..
for col_name in df.columns:
if(df[col_name].dtype == 'object'):
df[col_name]= df[col_name].astype('category')
df[col_name] = df[col_name].cat.codes
这会将所有字符串/对象类型列转换为分类。然后将代码应用于每种类型的类别。
【讨论】:
【参考方案12】:这对我有用:
pandas.factorize( ['B', 'C', 'D', 'B'] )[0]
输出:
[0, 1, 2, 0]
【讨论】:
被低估的答案 很好,比公认的答案简单得多 我同意,这是一个非常好的和有效的答案 最佳答案,恕我直言【参考方案13】:@Quickbeam2k1,见下文-
dataset=pd.read_csv('Data2.csv')
np.set_printoptions(threshold=np.nan)
X = dataset.iloc[:,:].values
使用 sklearn
from sklearn.preprocessing import LabelEncoder
labelencoder_X=LabelEncoder()
X[:,0] = labelencoder_X.fit_transform(X[:,0])
【讨论】:
你为什么不更正你之前的答案?令人惊讶的是,您现在使用的是fit_transform
而不是 transform_fit
,并更正了 labelencoder 定义。为什么使用iloc[:,:]
?这是没用的。图片背后的原因是什么?如果你想证明我和@theGtknerd 你失败了。【参考方案14】:
如果您只是担心创建一个额外的列并稍后将其删除,那么首先不要使用新列。
dataframe = pd.DataFrame('col1':[1,2,3,4,5], 'col2':list('abcab'), 'col3':list('ababb'))
dataframe.col3 = pd.Categorical.from_array(dataframe.col3).codes
你已经完成了。现在Categorical.from_array
已被弃用,直接使用Categorical
dataframe.col3 = pd.Categorical(dataframe.col3).codes
如果您还需要从索引到标签的映射,还有更好的方法
dataframe.col3, mapping_index = pd.Series(dataframe.col3).factorize()
查看下方
print(dataframe)
print(mapping_index.get_loc("c"))
【讨论】:
【参考方案15】:首先,要将分类列转换为其数字代码,您可以使用以下方法更轻松地完成此操作:dataframe['c'].cat.codes
。
此外,可以使用select_dtypes
自动选择数据框中具有特定 dtype 的所有列。这样,您可以在多个自动选择的列上应用上述操作。
首先制作一个示例数据框:
In [75]: df = pd.DataFrame('col1':[1,2,3,4,5], 'col2':list('abcab'), 'col3':list('ababb'))
In [76]: df['col2'] = df['col2'].astype('category')
In [77]: df['col3'] = df['col3'].astype('category')
In [78]: df.dtypes
Out[78]:
col1 int64
col2 category
col3 category
dtype: object
然后通过使用select_dtypes
选择列,然后在每个列上应用.cat.codes
,可以得到以下结果:
In [80]: cat_columns = df.select_dtypes(['category']).columns
In [81]: cat_columns
Out[81]: Index([u'col2', u'col3'], dtype='object')
In [83]: df[cat_columns] = df[cat_columns].apply(lambda x: x.cat.codes)
In [84]: df
Out[84]:
col1 col2 col3
0 1 0 0
1 2 1 1
2 3 2 0
3 4 0 1
4 5 1 1
【讨论】:
有没有一种简单的方法可以得到类别代码和类别字符串值之间的映射? 你可以使用:df['col2'].cat.categories
例如。
向任何担心这会将NaN
唯一映射到-1
的人指出
爱 2 衬里 ;)
请注意,如果分类是有序的(序数),则cat.codes
返回的数字代码可能不是您在系列中看到的数字代码!以上是关于转换熊猫数据框中的分类数据的主要内容,如果未能解决你的问题,请参考以下文章
如何将熊猫数据框中的嵌套逗号分隔列转换为Python中的特定格式
带有熊猫数据框输入的 sklearn 分类报告产生:“TypeError:并非所有参数都在字符串格式化期间转换”