Home > database > ensemble_qid_x_qid_table.m

ensemble_qid_x_qid_table

PURPOSE ^

Produces a table comparing two question IDs.

SYNOPSIS ^

function an_st = ensemble_qid_x_qid_table(data_st,params)

DESCRIPTION ^

 Produces a table comparing two question IDs.
 an_st = ensemble_qid_x_qid_table(data_st,params);

 Produces a table in which the levels for one question ID form the columns and
 the levels for the other question ID form the rows.

 params.table.qid_order = compqid values specifying row, column order
 params.report.tables.print = should table be printed
 params.report.tables.write2file - should table be written to a file

CROSS-REFERENCE INFORMATION ^

This function calls: This function is called by:

SUBFUNCTIONS ^

SOURCE CODE ^

0001 function an_st = ensemble_qid_x_qid_table(data_st,params)
0002 % Produces a table comparing two question IDs.
0003 % an_st = ensemble_qid_x_qid_table(data_st,params);
0004 %
0005 % Produces a table in which the levels for one question ID form the columns and
0006 % the levels for the other question ID form the rows.
0007 %
0008 % params.table.qid_order = compqid values specifying row, column order
0009 % params.report.tables.print = should table be printed
0010 % params.report.tables.write2file - should table be written to a file
0011 
0012 % 05/18/07 PJ - added conn_id support, and resolution of
0013 % {'display','report'} ambiguity
0014 % 03/03/11 PJ - added support for checkbox enums; implemented handling
0015 % (though not quite ideal) of multiple instances of question/stimulus
0016 % combinations
0017 % 01Sep2014 PJ - improved conn_id support
0018 
0019 if isfield(params,'mysql')
0020   conn_id = params.mysql.conn_id;
0021 elseif isfield(params,'ensemble')
0022   conn_id = params.ensemble.conn_id;
0023 else
0024   conn_id = 1;
0025   tmp_conn_id = 1;
0026 end
0027 
0028 if isfield(params,'display')
0029   report_str = 'display';
0030 elseif isfield(params, 'report')
0031   report_str = 'report';
0032 else
0033   report_str = 'report';
0034   params.report.tables.print = 0;
0035   params.report.tables.write2file = 0;
0036 end
0037 
0038 an_st = {};
0039 na = 0;
0040 
0041 % Set the column constants
0042 incol = set_var_col_const(data_st.vars);
0043 
0044 % Make sure that we have either compqid or question and subquestion ID information
0045 if ~isfield(incol,'compqid') && ~all(isfield(incol,{'question_id','subquestion'}))
0046   fprintf(['Did not find necessary question and subquestion or composite question ID' ...
0047     ' information in the input data']);
0048   return
0049 end
0050 
0051 % Generate the compqid for each row in the data if necessary
0052 if ~isfield(incol,'compqid')
0053   data_st.vars{end+1} = 'compqid';
0054   data_st.data{end+1} = make_compqid(data_st.data{incol.question_id}, ...
0055       data_st.data{incol.subquestion});
0056   incol = set_var_col_const(data_st.vars);
0057 end
0058 
0059 % Apply any specified filtering to the input data
0060 if isfield(params,'filt')
0061   fprintf('Applying filtering criteria\n')
0062   data_st = ensemble_filter(data_st, params.filt);
0063 end
0064 
0065 % Make sure we only have two compqids
0066 qids = unique(data_st.data{incol.compqid});
0067 nqid = length(qids);
0068 
0069 if nqid < 2
0070   fprintf('ensemble_qid_x_qid_table: Too few qids\n');
0071   return
0072 elseif nqid > 2
0073   fprintf('ensemble_qid_x_qid_table: Too many (%d) qids\n', nqid);
0074   return
0075 end
0076 
0077 % Figure out how many categories we have in each of the questions
0078 qinfo = mysql_extract_metadata('table','question',...
0079     'question_id',fix(qids), ...
0080     'conn_id', conn_id);
0081 qinfo(~ismember([qinfo.compqid],qids)) = [];
0082 
0083 rowqid_idx = find([qinfo.compqid] == params.table.qid_order(1));
0084 colqid_idx = find([qinfo.compqid] == params.table.qid_order(2));
0085 rowcats = qinfo(rowqid_idx).enum_values;
0086 colcats = qinfo(colqid_idx).enum_values;
0087 rowcats{end+1} = 'Total';
0088 colcats{end+1} = 'Total';
0089 
0090 % Check to see if we are dealing with a checkbox
0091 is_checkbox.row = strcmp(qinfo(rowqid_idx).html_field_type, 'checkbox');
0092 is_checkbox.col = strcmp(qinfo(colqid_idx).html_field_type, 'checkbox');
0093 
0094 nrows = length(rowcats);
0095 ncols = length(colcats);
0096 
0097 subids = unique(data_st.data{incol.subject_id});
0098 nsubs = length(subids);
0099 
0100 cntmtx = zeros(nrows,ncols,nsubs);
0101 propmtx = zeros(nrows,ncols,nsubs);
0102 
0103 % Initialize an analysis structure
0104 na = na+1;
0105 
0106 an_st{na} = init_analysis_struct;
0107 an_st{na}.type = 'table_qid_x_qid_x_sub';
0108 an_vars = {'subject_id','row_categories','col_categories','count','prop','nstim'};
0109 an_st{na}.vars = an_vars;
0110 an_cols = set_var_col_const(an_vars);
0111   
0112 an_st{na}.data{an_cols.subject_id} = subids;  
0113 an_st{na}.data{an_cols.row_categories} = rowcats;  
0114 an_st{na}.data{an_cols.col_categories} = colcats;  
0115 
0116 % Loop over subjects and stimuli to figure out how many items fall into each
0117 % question combination
0118 for isub = 1:nsubs
0119   filt.include.any.subject_id = subids(isub);
0120   subdata = ensemble_filter(data_st,filt);
0121   
0122   stimids = unique(subdata.data{incol.stimulus_id});
0123   nstim = length(stimids);
0124   
0125   % Generate the question ID masks
0126   rowqid_mask = subdata.data{incol.compqid} == params.table.qid_order(1);
0127   colqid_mask = subdata.data{incol.compqid} == params.table.qid_order(2);
0128   
0129   for istim = 1:nstim
0130     stim_mask = subdata.data{incol.stimulus_id} == stimids(istim);
0131     
0132     composite_row_mask = stim_mask & rowqid_mask;
0133     composite_col_mask = stim_mask & colqid_mask;
0134     
0135     % Make sure we have a response to the row question
0136     num_instances = sum(composite_row_mask);
0137     if ~num_instances
0138       continue
0139     elseif num_instances > 1
0140       fprintf('Multiple (%d) stim_id/question combinations: sub=%s, stimid=%d\n', ...
0141         num_instances, subids{isub}, stimids(istim));
0142       fprintf('Using first instance ...\n');
0143       idxs = find(composite_row_mask);
0144       composite_row_mask(idxs(2:end)) = 0;
0145     end
0146     
0147     % Make sure we have a response to the column question
0148     num_instances = sum(composite_col_mask);
0149     if ~num_instances
0150       continue
0151     elseif num_instances > 1
0152       fprintf('Multiple (%d) stim_id/question combinations: sub=%s, stimid=%d\n', ...
0153         num_instances, subids{isub}, stimids(istim));
0154       fprintf('Using first instance ...\n');
0155       idxs = find(composite_col_mask);
0156       composite_col_mask(idxs(2:end)) = 0;
0157     end
0158     
0159     
0160     if is_checkbox.row
0161       row_idx = find(data2bitmask(subdata.data{incol.response_enum}(composite_row_mask),...
0162         length(qinfo(rowqid_idx).enum_values)));
0163     else
0164       row_idx = ...
0165         enum2data(subdata.data{incol.response_enum}(composite_row_mask));
0166     end
0167     
0168     if is_checkbox.col
0169       col_idx = find(data2bitmask(subdata.data{incol.response_enum}(composite_col_mask),...
0170         length(qinfo(colqid_idx).enum_values)));
0171     else
0172       col_idx = ...
0173         enum2data(subdata.data{incol.response_enum}(stim_mask&colqid_mask));
0174     end
0175     
0176     cntmtx(row_idx,col_idx,isub) = cntmtx(row_idx,col_idx,isub)+1;
0177     
0178     % Update marginal counts
0179     cntmtx(row_idx,ncols,isub) = cntmtx(row_idx,ncols,isub)+1;
0180     cntmtx(nrows,col_idx,isub) = cntmtx(nrows,col_idx,isub)+1;
0181   end % for istim
0182   
0183   % Count the total number of stims
0184   cntmtx(nrows,ncols,isub) = sum(cntmtx(:,ncols,isub));
0185   propmtx(:,:,isub) = cntmtx(:,:,isub)/cntmtx(nrows,ncols,isub);
0186 end % for isub=
0187 
0188 an_st{na}.data{an_cols.count} = cntmtx;
0189 an_st{na}.data{an_cols.prop} = propmtx;
0190 an_st{na}.data{an_cols.nstim} = squeeze(cntmtx(nrows,ncols,:));
0191 an_st{na}.report.printfun = @print_tables;
0192 
0193 % Print the info if desired
0194 if params.(report_str).tables.print || params.(report_str).tables.write2file
0195   an_st{na}.report.printfun(an_st{na},params.(report_str).tables);
0196 end
0197 
0198 if(exist('tmp_conn_id','var'))
0199   mysql(conn_id,'close');
0200 end
0201 
0202 end % ensemble_qid_x_qid_table
0203 
0204 function an_st = init_analysis_struct
0205   an_st.type = '';
0206   an_st.vars = {};
0207   an_st.data = {};
0208   an_st.meta = [];
0209   
0210 end % function an_st = init_analysis_struct
0211 
0212 function print_tables(an_st,params)
0213 
0214   fid = 1;
0215   if isfield(params,'write2file') && params.write2file
0216     fid = fopen(params.fname,'wt');
0217     if fid ~= -1
0218       fprintf('Writing table to file: %s\n', params.fname);
0219     else
0220       fid = 1;
0221     end
0222   end
0223 
0224   an_cols = set_var_col_const(an_st.vars);
0225   colcats = an_st.data{an_cols.col_categories};
0226   rowcats = an_st.data{an_cols.row_categories};
0227   nrows = length(rowcats);
0228   
0229   nsub = length(an_st.data{an_cols.subject_id});
0230   
0231   % Determine the number of subjects for whom we had no data
0232   num_bad_subs = unique(sum(isnan(an_st.data{an_cols.prop}),3));
0233   nsub = nsub-num_bad_subs;
0234   
0235   fprintf(fid,'\n\nTotal number of instances\n');
0236   fprintf(fid,'\n%s\n', sprintf('\t%s', colcats{:}));
0237   for irow = 1:nrows
0238     if nsub > 1
0239       data = sum(squeeze(an_st.data{an_cols.count}(irow,:,:)),2);
0240     else
0241       data = an_st.data{an_cols.count}(irow,:);
0242     end
0243     fprintf(fid,'%s%s\n', rowcats{irow}, sprintf('\t%d',data));
0244   end
0245   
0246   fprintf(fid,'\n\nAverage percentage (mean +/- sem)\n');
0247   fprintf(fid,'\n%s\n', sprintf('\t%s', colcats{:}));
0248   
0249   for irow = 1:nrows
0250     if nsub > 1
0251       data = nanmean(squeeze(an_st.data{an_cols.prop}(irow,:,:)),2);
0252       err = nanstd(squeeze(an_st.data{an_cols.prop}(irow,:,:)),[],2)/sqrt(nsub);
0253     else
0254       data = an_st.data{an_cols.prop}(irow,:);
0255       err = 0;
0256     end
0257     
0258     fprintf(fid,'%s%s\n', rowcats{irow}, sprintf('\t%2.1f (%2.1f)', [data err]'*100));
0259   end  
0260   
0261   if fid ~=1
0262     fclose(fid);
0263   end
0264 end

Generated on Wed 20-Sep-2023 04:00:50 by m2html © 2003