Preprocessing of Categorical Variables by Common
Quantification
2023.11: Revised
Machine learning uses One-Hot-encoding to preprocess categorical variables. One-Hot-encoding constructs dummy variables for each value of categorical variables. On the other hand, common quantification assigns values to categorical values so that variance of the categorical variable with respect to the assigned values becomes (locally) maximum and (locally) maximum information in the categorical variable is obtained (Okamoto, 2015: body of the text is written in English).
Consider the following example of categorical variables (Table 1).
=================================================
Table 1. Data with a categorical variable CatV.
ID CatV
A1 alpha
A2 alpha
A3 gamma
A4 alpha
A5 alpha
B1 alpha
B2 alpha
B3 alpha
B4 gamma
C1 beta
C2 beta
C3 gamma
C4 beta
D1 beta
D2 beta
D3 beta
D4 gamma
=================================================
Categorical variables can be given numerical values by the
proposed quantification. For example, in Table 1, quantification, by which
categories alpha, beta, and gamma are given numerical values, , and ,
respectively, is represented by the following equation.
Quantification values s can be
given by the following way:
Set
then we have
is called an
indicator matrix.
Set
then we have
Under the condition
we seek the , which
maximizes variance
This can be given
as an eigen vector in the following spectral decomposition
equation
where matrix is the
centered matrix of
When and are solution for eq. (1), then and are also solution for eq. (1). Hence, when
we calculate quantification, we may get weights, which are sign inverted. Both
weights are correct ones.
For detailes about the quantification, see Okamoto (2015), the body of
which is written in English.
Programs and sample data files are archived into commonqfiles.zip.
The programs and data files in the archived file commonqfiles.zip
can be freely used by the reader.
In the following, How to use the program,
Example1 (PCA and regression analysis) and Example 2 (PCA and
cross tabulation) of the application are presented.
The main script, which is shown in Listing
1, calls the function common_q of mymodule.py, which is shown in Listing 2. Listings 1 and 2 are shown at the end of the
website.
To run the program, execute the command
PS D:\******\commonqfiles> python MainCommonQ.py
When the program starts, the input data file name is asked
PS
D:\******\commonqfiles> python MainCommonQ.py
Data
File Name (*.xlsx) =
The input data file is an Excel file, as shown in Figure
1.1.
Figure 1.1 File name: Data.xlsx
In the first row, variable names are set. The second row
indicates how to process the values of each variable. 0 indicates no
transformation, 1 means that standardization of the variable will be done, and
integer K larger than 1 means that the number of categories of that variable is
K and quantification of the variable is required. Data values are set from the
third row.
Set an input Excel data file name. If you use the file shown
in Figure 1.1, set as follows:
Data File Name (*.xlsx) = Data.xlsx
After the input data file name is set, the program processes
the data. When the program ends, the terminal shows messages like the
following:
PS
D:******\commonqfiles> python .\MainCommonQ.py
Data
File Name (*.xlsx) = Data.xlsx
ndata
= 17
nvar
= 6
indx
=
['GrpID' 'ID' 'Score' 'Attr.' 'CA' 'CB']
cndtn
=
[0 0 0 1 3 3]
Quantified
Data was saved in cq_Data.xlsx
Log
file = q_Data.txt
PS
D:******\commonqfiles>
The quantified data was saved as an Excel file of the file
name with prefix gcq_h to the input data file name.
Open this file, you can see the one shown in Figure 1.2 in
the case of the input data file shown in Figure 1.1.
Figure 1.2 Processed file: cq_Data.xlsx
Compare Figure 1.2 with Figure 1.1. Standardized variable
Attr is given the name Attr_z with suffix to the variable name. Quantified
variables CA and CB have prefix gq_h, each of which
has suffix like g_ih. The
suffix g_ih is added to the
i-th quantification variable with i starting from 0.
Open the log file, q_Data.txt, the name of which is shown in
the terminal after the program ended. The name of the log file is one with the
prefix gq_h to the input data file name, and the
file extension is replaced by g.txth.
In the log file, you can see the values of weights for
quantification as follows:
Data
file = Data.xlsx
Quantification
of CA
eigen
values = [6.49239444 4.56642909]
Created...q_CA_0 for lambda = 6.4924
with omega = 0.74653
-0.65965 -0.08688
Created...q_CA_1 for lambda = 4.5664
with omega = -0.33069
-0.48117 0.81186
Quantification
of CB
eigen
values = [6.49239444 4.56642909]
Created...q_CB_0 for lambda = 6.4924
with omega = 0.74653
-0.65965 -0.08688
Created...q_CB_1 for lambda = 4.5664
with omega = -0.33069
-0.48117 0.81186
Output
file = cq_Data.xlsx
Example
1. Categorical variable and continuous variable
Data in Figure 2.1 is hypothetical data, with variables
DataID, species, and p_length.
Figure 2.1 Hypothetical data.
To prepare for quantification of the categorical variable
species, categories Virginia, versicolor, and setosa are replaced by integers
1, 2, and 3. The quantification program assumes that categorical variable takes
an integer value from 1 to K when the number of categories is K. Correspondence
between the category and an integer is arbitrary, that is, categories are
considered in the nominal scale.
Figure 2.2 Data file for
quantification
Quantification of the data in Figure 2.2 gives the results
shown in Figure 2.3.
Figure 2.3 Quantification of the
data in Figure 2.2
Content of the log file is as follows:
Data
file = Data_irisK_1.xlsx
Quantification
of species
eigen
values = [3.6 3. ]
Created...q_species_0 for lambda = 3.6
with omega = 0.8165
-0.40825 -0.40825
Created...q_species_1 for lambda = 3.0
with omega = -4.1869e-16
-0.70711 0.70711
Output
file = cq_Data_irisK_1.xlsx
Analyze the three variables, q_species_0, q_species_1, and
p_length_z, by principal component analysis (PCA), then we get the results
shown in Figure 2.4. PCA may produce a sign inverted solution. Both solutions
are correct
Figure 2.4 Result of PCA
We see that q_species_0 and p_length_z have some relationship.
Analyze relation of variables q_species_0 and p_length_z by simple regression
model, then we get the result shown in Figure 2.5.
Figure 2.5 Regression analysis
In Figure 2.5, small random fluctuations are added to the
horizontal coordinates to avoid overlapping of points.
Quantification q_species_0 represents
Virginia, versicolor and setosa by weights 0.8165, -0.40824 and -0.40824 (See
the log file shown above). Figure 2.5 shows that p_length_z has larger values
for Virginia than for versicolor and setosa.
Exa,ple
2. Two categorical variables
Hypothetical data of eye color and hair color is shown in
Figure 3.1.
Figure 3.1 Hypothetical data
To quantify categorical data, categories Blue, Brown and
Hazel of eye colors are replaced by integers 1, 2, and 3, and Black, Bluenette,
and Red are replaced by integers 1, 2, and 3 (Figure 3.2). Quantification
program assumes that categorical variable takes an integer value from 1 to K
when the number of categories is K. Correspondence between the category and an
integer is arbitrary.
Figure 3.2 Data file for quantification
The results of quantification of the data in Figure 3.2 is
shown in Figure 3.3.
Figure 3.3 Quantification of the data in Figure 3.2
Content of the log file is as follows:
Data
file = Data_ColorK.xlsx
Quantification
of Eye
eigen
values = [3.88102497 2.31897503]
Created...q_Eye_0 for lambda = 3.881
with
omega = 0.59554 -0.7815 0.18596
Created...q_Eye_1 for lambda = 2.319
with omega = -0.55856
-0.23647 0.79504
Quantification
of Hair
eigen
values = [3.88102497 2.31897503]
Created...q_Hair_0 for lambda = 3.881
with omega = -0.18596
-0.59554 0.7815
Created...q_Hair_1 for lambda = 2.319
with omega = -0.79504
0.55856 0.23647
Output
file = cq_Data_ColorK.xlsx
PCA of the quantified data in Figure 3.3 gives the results
in Figure 3.4. PCA may produce a sign inverted solution. Both solutions are
correct.
Figure 3.4 PCA
Quantifications q_Eye_1 and q_Hair_0 look to be closely
related, and q_Eye_0 and q_Hair_1 also look to be closely related.
As an example, consider relation between q_Eye_1 and
q_Hair_0.
Construct a cross table of q_Eye_1 and q_Hair_0 by the
following script:
import
pandas as pd
import
numpy as np
with
pd.ExcelFile('Data_Color.xlsx') as xlsx:
data = pd.read_excel(xlsx)
xt
= pd.crosstab(np.array(data['Eye']), np.array(data['Hair']),
rownames = ['Eye'], colnames = ['Hair'])
print('\nCross
Table(DataFrame) =\n', xt)
xt
= np.array(xt)
print('\nCross
Table(nparray) =\n', xt)
w_eye_1
= [-0.55856, -0.23647, 0.79504]
w_hair_0
= [-0.18596, -0.59554, 0.7815]
idx_eye_1
= np.argsort(w_eye_1)
idx_hair_0
= np.argsort(w_hair_0)
print('\nw_eye_1
=\n', w_eye_1)
print('\nidx_eye_1
=\n', idx_eye_1)
print('w_hair_0
|n', w_hair_0)
print('idx_hair_0
=\n', idx_hair_0)
s_xt
= xt[idx_eye_1][:,idx_hair_0]
print('\nRearranged
Cross Table =\n', s_xt)
Run the script, then the following output is displayed on
the terminal
Cross
Table(DataFrame) =
Hair Black Bluenette Red
Eye
Blue 0
3 0
Brown 2
0 3
Hazel 0
0 2
Cross
Table(nparray) =
[[0 3 0]
[2 0 3]
[0 0 2]]
w_eye_1
=
[-0.55856, -0.23647, 0.79504]
idx_eye_1
=
[0 1 2]
w_hair_0
|n [-0.18596, -0.59554, 0.7815]
idx_hair_0
=
[1 0 2]
Rearranged
Cross Table =
[[3 0 0]
[0 2 3]
[0 0 2]]
Rows and Columns of the cross table created by pandas are
ordered alphabetically. After rearranging rows and columns according to weights
for the variables, the relation between the variables becomes to be seen more
clearly.
Reference
Okamoto,
Y. (2015). A Two-Step Analysis with Common Quantification of Categorical Data. Japan Womenfs University Journal: Faculty of
Integrated Arts and Social Sciences, 26, 99-112 (Body of
the text is written in English).
Listing 1 Main script MainCommonQ.py
import
pandas as pd
import
scipy.stats as ss
import
numpy as np
import
mymodule as mm
flnm
= input('Data File Name (*.xlsx) = ')
fout_nm
= 'q_' + flnm[:-4] + 'txt'
fout
= open(fout_nm, 'w')
fout.write('Data
file = ' + flnm)
xlsx
= pd.ExcelFile(flnm)
data
= pd.read_excel(xlsx)
X
= data.values[1:]
ndata
= len(X)
print('ndata
= ', ndata)
indx
= data.columns.values
cndtn
= data.values[0]
nvar
= len(indx)
print('nvar
= ', nvar)
print('indx
=\n', indx)
print('cndtn
=\n', cndtn)
temp_df
= pd.DataFrame()
for
i in range(nvar):
if (cndtn[i] < 0):
print('condition for var-{} < 0'.format(i))
raise 'var_cond error.'
else:
if
(cndtn[i] == 0):
temp_df[indx[i]] = X[:, i]
elif
(cndtn[i] == 1):
temp_df[indx[i] + '_z'] = ss.zscore([x for x in X[:, i]])
else:
nq, varnames, qvars = mm.common_q(cndtn[i], indx[i], X[:, i], fout)
for j in range(nq):
temp_df[varnames[j]] = qvars[j]
with pd.ExcelWriter('cq_' + flnm) as
xl_writer:
temp_df.to_excel(xl_writer,
index = False)
print('\nQuantified
Data was saved in ' + 'cq_' + flnm)
fout.write('\n\nOutput
file = ' + 'cq_' + flnm)
fout.close()
print('\nLog
file = ' + fout_nm + '\n')
import
numpy as np
import
scipy as sc
def
common_q(K, vname, X, fout):
fout.write('\n\nQuantification
of {}'.format(vname))
nq = K - 1
n = len(X)
G = np.zeros((n, K))
for i in range(n):
G[i,
X[i] - 1] = 1.0
f = G.sum(axis = 0)
for k in range(K):
if
f[k] == 0:
print('Category-{0} of variable {1} is not used.'.format(k+1, vname))
fout.write('\n\nCategory-{0} of variable {1} is not used.'.format(k+1,
vname))
fout.close()
raise Exception('Category Error !')
One_n = np.ones((n, 1))
f = np.reshape(f, (1, K))
H = G - One_n @ f / n
HpH = H.T @ H
wt, vctr =
np.linalg.eig(HpH)
ck_idx = np.abs(wt) >
1.0e-7
wt = wt[ck_idx]
vctr = vctr[:, ck_idx]
idx = np.argsort(-wt)
wt = wt[idx]
vctr = vctr.T[idx].T
fout.write('\neigen values =
{}'.format(wt))
nq = len(wt)
qnames = []
qvars = []
for h in range(nq): #K - 1):
qnames.append('q_' + vname + '_{}'.format(h))
z =
H @ np.reshape(vctr[:,h], (K, 1)) / ((wt[h]/n) ** 0.5)
qvars.append(z)
fout.write('\nCreated...{0:s}
for lambda = {1:.5}\n'.format(qnames[-1], wt[h]))
fout.write('
with omega = ')
for
j in range(K):
fout.write('{0:.5}
'.format(vctr[j][h]))
return nq, qnames, qvars