[gnumeric] Extend regression tool to perform multiple simple regressions. [#614031]
- From: Andreas J. Guelzow <guelzow src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnumeric] Extend regression tool to perform multiple simple regressions. [#614031]
- Date: Wed, 31 Mar 2010 06:45:29 +0000 (UTC)
commit 8ae1db236e15b06d3e8f463b3ec9eac21da1cdd3
Author: Andreas J. Guelzow <aguelzow pyrshep ca>
Date: Wed Mar 31 00:44:45 2010 -0600
Extend regression tool to perform multiple simple regressions. [#614031]
2010-03-31 Andreas J. Guelzow <aguelzow pyrshep ca>
* regression.glade: add radio buttons
* dialog-analysis-tools.c (regression_tool_ok_clicked_cb): handle
new radio buttons
2010-03-31 Andreas J. Guelzow <aguelzow pyrshep ca>
* analysis-tools.h (analysis_tools_data_regression_t): add fields
* analysis-tools.c (analysis_tools_remove_label): change arguments
and change all callers
(analysis_tools_write_a_label): new
(analysis_tool_regression_simple_engine_run): new
(analysis_tool_regression_engine): hook up second engine
NEWS | 2 +
src/dialogs/ChangeLog | 6 +
src/dialogs/dialog-analysis-tools.c | 3 +
src/dialogs/regression.glade | 100 ++++++++++++++-----
src/tools/ChangeLog | 9 ++
src/tools/analysis-tools.c | 183 +++++++++++++++++++++++++++++++++--
src/tools/analysis-tools.h | 2 +
7 files changed, 269 insertions(+), 36 deletions(-)
---
diff --git a/NEWS b/NEWS
index 5139fc7..80632df 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,8 @@ Andreas:
* Fix column and row header display under Quartz. [#600085]
* Fix preferences in gconf-less situations. [#613523]
* Implement first letter capitalization. [#613768]
+ * Extend regression tool to perform multiple simple regressions.
+ [#614031]
Morten:
* Improve object sizing tooltip positioning a bit.
diff --git a/src/dialogs/ChangeLog b/src/dialogs/ChangeLog
index 63afd77..38c5315 100644
--- a/src/dialogs/ChangeLog
+++ b/src/dialogs/ChangeLog
@@ -1,3 +1,9 @@
+2010-03-31 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * regression.glade: add radio buttons
+ * dialog-analysis-tools.c (regression_tool_ok_clicked_cb): handle
+ new radio buttons
+
2010-03-25 Andreas J. Guelzow <aguelzow pyrshep ca>
* dialog-preferences.c (int_pref_widget_to_conf): get the
diff --git a/src/dialogs/dialog-analysis-tools.c b/src/dialogs/dialog-analysis-tools.c
index 4392e8c..d7fdebf 100644
--- a/src/dialogs/dialog-analysis-tools.c
+++ b/src/dialogs/dialog-analysis-tools.c
@@ -2149,6 +2149,9 @@ regression_tool_ok_clicked_cb (G_GNUC_UNUSED GtkWidget *button,
w = glade_xml_get_widget (state->base.gui, "intercept-button");
data->intercept = 1 - gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
+ w = glade_xml_get_widget (state->base.gui, "multiple-regression-button");
+ data->multiple_regression = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (w));
+
if (cmd_analysis_tool (WORKBOOK_CONTROL (state->base.wbcg), state->base.sheet,
dao, data, analysis_tool_regression_engine)) {
char *text;
diff --git a/src/dialogs/regression.glade b/src/dialogs/regression.glade
index 5401912..f902c84 100644
--- a/src/dialogs/regression.glade
+++ b/src/dialogs/regression.glade
@@ -1,7 +1,7 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
-<!--*- mode: xml -*-->
+<?xml version="1.0"?>
<glade-interface>
+ <!-- interface-requires gtk+ 2.6 -->
+ <!-- interface-naming-policy toplevel-contextual -->
<widget class="GtkDialog" id="Regression">
<property name="title" translatable="yes">Regression</property>
<property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
@@ -23,15 +23,6 @@
<property name="column_spacing">12</property>
<property name="row_spacing">6</property>
<child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child>
<widget class="GtkLabel" id="var1-label">
<property name="visible">True</property>
<property name="xalign">0</property>
@@ -63,11 +54,11 @@
</child>
<child>
<widget class="GtkCheckButton" id="labels_button">
+ <property name="label" translatable="yes">_Labels</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="label" translatable="yes">_Labels</property>
+ <property name="receives_default">False</property>
<property name="use_underline">True</property>
- <property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
@@ -77,6 +68,15 @@
<property name="y_options"></property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</widget>
</child>
<child>
@@ -86,8 +86,8 @@
<property name="use_underline">True</property>
</widget>
<packing>
- <property name="type">tab</property>
<property name="tab_fill">False</property>
+ <property name="type">tab</property>
</packing>
</child>
<child>
@@ -107,13 +107,13 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkEntry" id="confidence-entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
- <property name="invisible_char">*</property>
<property name="text" translatable="yes">0.95</property>
</widget>
<packing>
@@ -124,16 +124,17 @@
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
<widget class="GtkCheckButton" id="intercept-button">
+ <property name="label" translatable="yes">_Force intercept to be zero</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
+ <property name="receives_default">False</property>
<property name="border_width">3</property>
- <property name="label" translatable="yes">_Force intercept to be zero</property>
<property name="use_underline">True</property>
- <property name="response_id">0</property>
<property name="draw_indicator">True</property>
</widget>
<packing>
@@ -143,6 +144,41 @@
</packing>
</child>
<child>
+ <widget class="GtkRadioButton" id="multiple-regression-button">
+ <property name="label" translatable="yes">_Multiple linear regression</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="border_width">3</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <widget class="GtkRadioButton" id="simple-regression-button">
+ <property name="label" translatable="yes">Multiple 2-_variable regressions</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="border_width">3</property>
+ <property name="use_underline">True</property>
+ <property name="active">True</property>
+ <property name="draw_indicator">True</property>
+ <property name="group">multiple-regression-button</property>
+ </widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ <child>
<placeholder/>
</child>
</widget>
@@ -157,9 +193,9 @@
<property name="use_underline">True</property>
</widget>
<packing>
- <property name="type">tab</property>
<property name="position">1</property>
<property name="tab_fill">False</property>
+ <property name="type">tab</property>
</packing>
</child>
<child>
@@ -180,9 +216,9 @@
<property name="use_underline">True</property>
</widget>
<packing>
- <property name="type">tab</property>
<property name="position">2</property>
<property name="tab_fill">False</property>
+ <property name="type">tab</property>
</packing>
</child>
</widget>
@@ -193,7 +229,7 @@
<child>
<widget class="GtkLabel" id="warnings">
<property name="visible">True</property>
- <property name="justify">GTK_JUSTIFY_CENTER</property>
+ <property name="justify">center</property>
</widget>
<packing>
<property name="position">2</property>
@@ -205,38 +241,47 @@
<property name="layout_style">GTK_BUTTONBOX_END</property>
<child>
<widget class="GtkButton" id="helpbutton">
+ <property name="label">gtk-help</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
- <property name="label">gtk-help</property>
+ <property name="receives_default">False</property>
<property name="use_stock">True</property>
- <property name="response_id">0</property>
</widget>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
</child>
<child>
<widget class="GtkButton" id="cancelbutton">
+ <property name="label">gtk-cancel</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
- <property name="label">gtk-cancel</property>
+ <property name="receives_default">False</property>
<property name="use_stock">True</property>
- <property name="response_id">0</property>
</widget>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<widget class="GtkButton" id="okbutton">
+ <property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="can_default">True</property>
<property name="has_default">True</property>
- <property name="label">gtk-ok</property>
+ <property name="receives_default">False</property>
<property name="use_stock">True</property>
- <property name="response_id">0</property>
</widget>
<packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
@@ -244,6 +289,7 @@
<packing>
<property name="expand">False</property>
<property name="pack_type">GTK_PACK_END</property>
+ <property name="position">0</property>
</packing>
</child>
</widget>
diff --git a/src/tools/ChangeLog b/src/tools/ChangeLog
index c0b4dc2..4a24143 100644
--- a/src/tools/ChangeLog
+++ b/src/tools/ChangeLog
@@ -1,3 +1,12 @@
+2010-03-31 Andreas J. Guelzow <aguelzow pyrshep ca>
+
+ * analysis-tools.h (analysis_tools_data_regression_t): add fields
+ * analysis-tools.c (analysis_tools_remove_label): change arguments
+ and change all callers
+ (analysis_tools_write_a_label): new
+ (analysis_tool_regression_simple_engine_run): new
+ (analysis_tool_regression_engine): hook up second engine
+
2010-03-28 Morten Welinder <terra gnome org>
* goal-seek.c (update_data): Properly handle NaNs. Fixes #614147.
diff --git a/src/tools/analysis-tools.c b/src/tools/analysis-tools.c
index 7b097f2..40ecf27 100644
--- a/src/tools/analysis-tools.c
+++ b/src/tools/analysis-tools.c
@@ -129,17 +129,15 @@ cb_adjust_areas (gpointer data, G_GNUC_UNUSED gpointer user_data)
/*
* analysis_tools_remove_label:
- * @val: range to extract label from
- * @info: analysis_tools_data_generic_t info
*
*/
static void
analysis_tools_remove_label (GnmValue *val,
- analysis_tools_data_generic_t *info)
+ gboolean labels, group_by_t group_by)
{
- if (info->labels) {
- switch (info->group_by) {
+ if (labels) {
+ switch (group_by) {
case GROUPED_BY_ROW:
val->v_range.cell.a.col++;
break;
@@ -178,7 +176,7 @@ analysis_tools_write_label (GnmValue *val, data_analysis_output_t *dao,
label->v_range.cell.b = label->v_range.cell.a;
dao_set_cell_expr (dao, x, y, gnm_expr_new_constant (label));
- analysis_tools_remove_label (val, info);
+ analysis_tools_remove_label (val, info->labels, info->group_by);
} else {
switch (info->group_by) {
case GROUPED_BY_ROW:
@@ -201,6 +199,54 @@ analysis_tools_write_label (GnmValue *val, data_analysis_output_t *dao,
}
/*
+ * analysis_tools_write_label:
+ * @val: range to extract label from
+ * @dao: data_analysis_output_t, where to write to
+ * @labels: analysis_tools_data_generic_t infowhether the
+ * @val contains label info
+ * @group_by: grouping info
+ * @x: output col number
+ * @y: output row number
+ * @i: default col/row number
+ *
+ */
+
+static void
+analysis_tools_write_a_label (GnmValue *val, data_analysis_output_t *dao,
+ gboolean labels, group_by_t group_by,
+ int x, int y)
+{
+ if (labels) {
+ GnmValue *label = value_dup (val);
+
+ label->v_range.cell.b = label->v_range.cell.a;
+ dao_set_cell_expr (dao, x, y, gnm_expr_new_constant (label));
+ analysis_tools_remove_label (val, labels, group_by);
+ } else {
+ char const *str = ((group_by == GROUPED_BY_ROW) ? "row" : "col");
+ char const *label = ((group_by == GROUPED_BY_ROW) ? _("Row") : _("Column"));
+
+ GnmFunc *fd_concatenate;
+ GnmFunc *fd_cell;
+
+ fd_concatenate = gnm_func_lookup_or_add_placeholder ("CONCATENATE", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+ gnm_func_ref (fd_concatenate);
+ fd_cell = gnm_func_lookup_or_add_placeholder ("CELL", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+ gnm_func_ref (fd_cell);
+
+ dao_set_cell_expr (dao, x, y, gnm_expr_new_funcall3
+ (fd_concatenate, gnm_expr_new_constant (value_new_string (label)),
+ gnm_expr_new_constant (value_new_string (" ")),
+ gnm_expr_new_funcall2 (fd_cell,
+ gnm_expr_new_constant (value_new_string (str)),
+ gnm_expr_new_constant (value_dup (val)))));
+
+ gnm_func_unref (fd_concatenate);
+ gnm_func_unref (fd_cell);
+ }
+}
+
+/*
* analysis_tools_write_label_ftest:
* @val: range to extract label from
* @dao: data_analysis_output_t, where to write to
@@ -3242,6 +3288,109 @@ analysis_tool_regression_engine_run (data_analysis_output_t *dao,
return FALSE;
}
+static gboolean
+analysis_tool_regression_simple_engine_run (data_analysis_output_t *dao,
+ analysis_tools_data_regression_t *info)
+{
+ GnmFunc *fd_linest;
+ GnmFunc *fd_index;
+ GnmFunc *fd_fdist;
+ GnmFunc *fd_rows;
+ GnmFunc *fd_columns;
+
+ GSList *inputdata;
+ guint row;
+
+ GnmValue *val_dep = value_dup (info->base.range_2);
+ GnmExpr const *expr_intercept = gnm_expr_new_constant (value_new_bool (info->intercept));
+ GnmExpr const *expr_observ;
+ GnmExpr const *expr_val_dep;
+
+ fd_linest = gnm_func_lookup_or_add_placeholder ("LINEST", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+ gnm_func_ref (fd_linest);
+ fd_index = gnm_func_lookup_or_add_placeholder ("INDEX", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+ gnm_func_ref (fd_index);
+ fd_fdist = gnm_func_lookup_or_add_placeholder ("FDIST", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+ gnm_func_ref (fd_fdist);
+ fd_rows = gnm_func_lookup_or_add_placeholder ("ROWS", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+ gnm_func_ref (fd_rows);
+ fd_columns = gnm_func_lookup_or_add_placeholder ("COLUMNS", dao->sheet ? dao->sheet->workbook : NULL, FALSE);
+ gnm_func_ref (fd_columns);
+
+ dao_set_italic (dao, 0, 0, 4, 0);
+ dao_set_italic (dao, 0, 2, 5, 2);
+ set_cell_text_row (dao, 0, 0, _("/SUMMARY OUTPUT"
+ "/"
+ "/Response Variable:"
+ "/"
+ "/Observations:"));
+ set_cell_text_row (dao, 0, 2, _("/Independent Variable"
+ "/R^2"
+ "/Slope"
+ "/Intercept"
+ "/F"
+ "/Significance of F"));
+ analysis_tools_write_a_label (val_dep, dao,
+ info->base.labels, info->group_by,
+ 3, 0);
+
+ expr_val_dep = gnm_expr_new_constant (val_dep);
+ dao_set_cell_expr (dao, 5, 0, gnm_expr_new_binary (gnm_expr_new_funcall1 (fd_rows, gnm_expr_copy (expr_val_dep)),
+ GNM_EXPR_OP_MULT,
+ gnm_expr_new_funcall1 (fd_columns, gnm_expr_copy (expr_val_dep))));
+ expr_observ = dao_get_cellref (dao, 5, 0);
+
+ for (row = 3, inputdata = info->indep_vars; inputdata != NULL;
+ inputdata = inputdata->next, row++) {
+ GnmValue *val_indep = value_dup (inputdata->data);
+ GnmExpr const *expr_linest;
+
+ dao_set_italic (dao, 0, row, 0, row);
+ analysis_tools_write_a_label (val_indep, dao,
+ info->base.labels, info->group_by,
+ 0, row);
+ expr_linest = gnm_expr_new_funcall4 (fd_linest,
+ gnm_expr_copy (expr_val_dep),
+ gnm_expr_new_constant (val_indep),
+ gnm_expr_copy (expr_intercept),
+ gnm_expr_new_constant (value_new_bool (TRUE)));
+ dao_set_cell_array_expr (dao, 1, row,
+ gnm_expr_new_funcall3 (fd_index,
+ gnm_expr_copy (expr_linest),
+ gnm_expr_new_constant (value_new_int (3)),
+ gnm_expr_new_constant (value_new_int (1))));
+ dao_set_cell_array_expr (dao, 4, row,
+ gnm_expr_new_funcall3 (fd_index,
+ gnm_expr_copy (expr_linest),
+ gnm_expr_new_constant (value_new_int (4)),
+ gnm_expr_new_constant (value_new_int (1))));
+ dao_set_array_expr (dao, 2, row, 2, 1, expr_linest);
+
+ dao_set_cell_expr (dao, 5, row, gnm_expr_new_funcall3
+ (fd_fdist,
+ make_cellref (-1, 0),
+ gnm_expr_new_constant (value_new_int (1)),
+ gnm_expr_new_binary (gnm_expr_copy (expr_observ),
+ GNM_EXPR_OP_SUB,
+ gnm_expr_new_constant (value_new_int (2)))));
+
+ }
+
+ gnm_expr_free (expr_intercept);
+ gnm_expr_free (expr_observ);
+ gnm_expr_free (expr_val_dep);
+
+ gnm_func_unref (fd_fdist);
+ gnm_func_unref (fd_linest);
+ gnm_func_unref (fd_index);
+ gnm_func_unref (fd_rows);
+ gnm_func_unref (fd_columns);
+
+ dao_redraw_respan (dao);
+
+ return FALSE;
+}
+
gboolean
analysis_tool_regression_engine (data_analysis_output_t *dao, gpointer specs,
analysis_tool_engine_t selector, gpointer result)
@@ -3256,11 +3405,22 @@ analysis_tool_regression_engine (data_analysis_output_t *dao, gpointer specs,
{
gint xdim = calculate_xdim (info->base.range_1, info->group_by);
- dao_adjust (dao, 7, 17 + xdim);
+ if (info->multiple_regression) {
+ info->indep_vars = NULL;
+ dao_adjust (dao, 7, 17 + xdim);
+ } else {
+ info->indep_vars = g_slist_prepend (NULL, info->base.range_1);
+ info->base.range_1 = NULL;
+ prepare_input_range (&info->indep_vars, info->group_by);
+ dao_adjust (dao, 6, 3 + xdim);
+ }
return FALSE;
}
case TOOL_ENGINE_CLEAN_UP:
+ range_list_destroy (info->indep_vars);
+ info->indep_vars = NULL;
return analysis_tool_generic_b_clean (specs);
+
case TOOL_ENGINE_LAST_VALIDITY_CHECK:
return FALSE;
case TOOL_ENGINE_PREPARE_OUTPUT_RANGE:
@@ -3270,7 +3430,10 @@ analysis_tool_regression_engine (data_analysis_output_t *dao, gpointer specs,
return dao_format_output (dao, _("Regression"));
case TOOL_ENGINE_PERFORM_CALC:
default:
- return analysis_tool_regression_engine_run (dao, specs);
+ if (info->multiple_regression)
+ return analysis_tool_regression_engine_run (dao, specs);
+ else
+ return analysis_tool_regression_simple_engine_run (dao, specs);
}
return TRUE; /* We shouldn't get here */
}
@@ -3948,7 +4111,9 @@ analysis_tool_anova_single_engine_run (data_analysis_output_t *dao, gpointer spe
GnmExpr const *expr_one;
GnmExpr const *expr_count_one;
- analysis_tools_remove_label (val_org, &info->base);
+ analysis_tools_remove_label (val_org,
+ info->base.labels,
+ info->base.group_by);
expr_one = gnm_expr_new_constant (value_dup (val_org));
arg_ss_total = gnm_expr_list_append
diff --git a/src/tools/analysis-tools.h b/src/tools/analysis-tools.h
index b5a4af5..a2e325c 100644
--- a/src/tools/analysis-tools.h
+++ b/src/tools/analysis-tools.h
@@ -166,6 +166,8 @@ typedef struct {
analysis_tools_data_generic_b_t base;
gint intercept;
group_by_t group_by;
+ gboolean multiple_regression;
+ GSList *indep_vars;
} analysis_tools_data_regression_t;
gboolean analysis_tool_regression_engine (data_analysis_output_t *dao, gpointer specs,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]