pd.get_dummies()在很大程度上很慢
我不确定这是否已经是最快的方法,或者如果我这样做效率低下。pd.get_dummies()在很大程度上很慢
我想热编码一个特定的具有27k +级别的分类列。列有2点不同的数据集不同的值,所以我第一次使用前get_dummies()
def hot_encode_column_in_both_datasets(column_name,df,df2,sparse=True):
col1b = set(df2[column_name].unique())
col1a = set(df[column_name].unique())
combined_cats = list(col1a.union(col1b))
df[column_name] = df[column_name].astype('category', categories=combined_cats)
df2[column_name] = df2[column_name].astype('category', categories=combined_cats)
df = pd.get_dummies(df, columns=[column_name],sparse=sparse)
df2 = pd.get_dummies(df2, columns=[column_name],sparse=sparse)
try:
del df[column_name]
del df2[column_name]
except:
pass
return df,df2
但是,它已经运行了2个多小时的联合水平,它仍然停留热码。
我可以在这里做错吗?还是仅仅是在大型数据集上运行它的本质?
Df有6.8m行和27列,Df2有19990行和27列,然后热编码我想要的列。
建议感激,谢谢! :)
我简要回顾了get_dummies source code,我认为它可能没有充分利用您的用例的稀疏性。下面的方法可以更快,但我并没有试图一路扩展它你有19M记录:
import numpy as np
import pandas as pd
import scipy.sparse as ssp
np.random.seed(1)
N = 10000
dfa = pd.DataFrame.from_dict({
'col1': np.random.randint(0, 27000, N)
, 'col2b': np.random.choice([1, 2, 3], N)
, 'target': np.random.choice([1, 2, 3], N)
})
# construct an array of the unique values of the column to be encoded
vals = np.array(dfa.col1.unique())
# extract an array of values to be encoded from the dataframe
col1 = dfa.col1.values
# construct a sparse matrix of the appropriate size and an appropriate,
# memory-efficient dtype
spmtx = ssp.dok_matrix((N, len(vals)), dtype=np.uint8)
# do the encoding. NB: This is only vectorized in one of the two dimensions.
# Finding a way to vectorize the second dimension may yield a large speed up
for idx, val in enumerate(vals):
spmtx[np.argwhere(col1 == val), idx] = 1
# Construct a SparseDataFrame from the sparse matrix and apply the index
# from the original dataframe and column names.
dfnew = pd.SparseDataFrame(spmtx, index=dfa.index,
columns=['col1_' + str(el) for el in vals])
dfnew.fillna(0, inplace=True)
UPDATE
借用其他答案见解here和here ,我能够在两个维度上矢量化解决方案。在我有限的测试中,我注意到构建SparseDataFrame似乎将执行时间增加了几倍。因此,如果您不需要返回类似DataFrame的对象,则可以节省大量时间。此解决方案还处理您需要将2+ DataFrames编码为具有相同列数的2-d数组的情况。
import numpy as np
import pandas as pd
import scipy.sparse as ssp
np.random.seed(1)
N1 = 10000
N2 = 100000
dfa = pd.DataFrame.from_dict({
'col1': np.random.randint(0, 27000, N1)
, 'col2a': np.random.choice([1, 2, 3], N1)
, 'target': np.random.choice([1, 2, 3], N1)
})
dfb = pd.DataFrame.from_dict({
'col1': np.random.randint(0, 27000, N2)
, 'col2b': np.random.choice(['foo', 'bar', 'baz'], N2)
, 'target': np.random.choice([1, 2, 3], N2)
})
# construct an array of the unique values of the column to be encoded
# taking the union of the values from both dataframes.
valsa = set(dfa.col1.unique())
valsb = set(dfb.col1.unique())
vals = np.array(list(valsa.union(valsb)), dtype=np.uint16)
def sparse_ohe(df, col, vals):
"""One-hot encoder using a sparse ndarray."""
colaray = df[col].values
# construct a sparse matrix of the appropriate size and an appropriate,
# memory-efficient dtype
spmtx = ssp.dok_matrix((df.shape[0], vals.shape[0]), dtype=np.uint8)
# do the encoding
spmtx[np.where(colaray.reshape(-1, 1) == vals.reshape(1, -1))] = 1
# Construct a SparseDataFrame from the sparse matrix
dfnew = pd.SparseDataFrame(spmtx, dtype=np.uint8, index=df.index,
columns=[col + '_' + str(el) for el in vals])
dfnew.fillna(0, inplace=True)
return dfnew
dfanew = sparse_ohe(dfa, 'col1', vals)
dfbnew = sparse_ohe(dfb, 'col1', vals)
嘿,谢谢你的回答! :)这将如何处理第二个数据框中类别的会计问题? – Wboy
你好! :)如果我正确理解这一点,这只会返回当前列作为一个稀疏的数据帧,而不是将它合并到原始数据帧的权利?此外,我得到一个ValueError:无法强制当前fill_value南试图将它uint8 dtype – Wboy
嗯,我不能重现ValueError。我使用熊猫0.20.1,这是最近才发布的。如果您需要重新组合包含原始列的所有列的完整数据框,那么可以在末尾添加此语句:'dfa = pd.concat([dfanew,dfa.drop( 'col1',axis = 1)],axis = 1)'。 – blueogive
'except:pass'总是错的。我想你想'如果column_name在df:'而是。至于你的问题的其余部分,你为什么不告诉我们哪一行需要很长时间? –
@JohnZwinck谢谢你的输入:)在这种情况下,我不认为它真的很重要,请纠正我,如果我错了。 – Wboy
@JohnZwinck正如我所提到的,get_dummies()需要很长的时间 – Wboy