HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Clinical decision tree using R

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
decisionclinicalusingtree

Problem

I'm trying to code this decision tree using R. I was wondering if there was a better way to go about this rather than using a ton of conditionals?

# ops
rm(list=ls(all=TRUE))
options(warn=-1)
saveFiles = FALSE
setwd("~/Documents/Education/UCLA/Spring 2016/MGMT271B/proj/")

# data vars
n = 10
T = c("X", seq(0,4), "is") 
N = c("X", seq(0,3)) 
M = c("X", seq(0,1)) 
S = c("1A", "1B", "2A", "2B", "3A", "3B", "3C", "4")
h = c("ductal", "lobular", "mixed", "metaplastic", "tubular", "mucinous")

# necessary functions
create_data  0.06 & TumorSize  0.06 & TumorSize  0.06 & TumorSize  1 & TumorSize < 3) {
          message(cat("Consider adjuvant endocrine therapy"))
        } else {
          message(cat("Adjuvant endocrine therapy"))
        }
      }
    } else if (ER == FALSE || PR == FALSE) {
      message(cat("Repeat determination of ER/PR status"))
    }
  } else {
    message(cat("Invalid Histology Status. Exiting"))
  }
}

# tests
n = 20 
data = create_data(n)
if(saveFiles){
  write.table(data, "data.tsv", sep="\t", col.names=NA)
  system("gzip data.tsv")  
}

get_patient_data(data, data$PatientID[1])
get_patient_data(data, "12857252013")
get_treatment_rec(Histology="ductal", ER=TRUE, PR=FALSE, HER2=TRUE, PrimaryTumor="T1", TumorSize=1.02, NearbyLymphNode="N1", Metastasis=NULL, Stage=NULL) 
get_treatment_rec(Histology="mucinous", ER=FALSE, PR=TRUE, HER2=TRUE, PrimaryTumor="T1", TumorSize=4.22, NearbyLymphNode="N0", Metastasis=NULL, Stage=NULL)

Solution

I think the common wisdom is to go data driven instead of hard coding
the tree. Then again, it's not clear if that helps too much here.

Let me suggest a few other things first to make the code a bit more
compact.

  • message(cat(...)) is used very often, but it seems the cat isn't


actually necessary here? Also, since all the function
get_treatment_rec does is to print/message the result, I'd say
that just returning the string and calling message outside of it is
far better in terms of composability,
i.e. message(get_treatment_rec(...)). Making use of the fact that R
will just return the last value in the function, it becomes much more
simple. There are also quite a number of "empty" cases - shouldn't
those also do something or at least return an error response?

  • Use && instead of & unless you really want to evaluate all


arguments. && and || are much more common since they can do less
work if the first parameter is already FALSE / TRUE respectively.

  • x == FALSE is usually written as !x unless you really only want to


match FALSE (not all "falsy" things). Same goes for x == TRUE
vs. just x.

  • Don't write something like if (foo) {} else if (!foo) {} - that's


unnecessary information as there's only two cases anyway, just use a
regular else branch instead, i.e. if (foo) {} else {}.

  • Now, there are recurring cases. I'd put those either into a variable


and only calculate them once (and name them), or put them into a
function and reuse that. Note that I have no idea what to name these,
so I'm using the usual foo, bar, baz, ... here.

For posterity I'm going to paste the resulting function, but it's really
just for illustration purposes:

get_treatment_rec  0.06 & TumorSize  0.06 & TumorSize  0.06 & TumorSize  1 && TumorSize < 3) {
          "Consider adjuvant endocrine therapy"
        } else {
          "Adjuvant endocrine therapy"
        }
      }
    } else if (!ER || !PR) {
      "Repeat determination of ER/PR status"
    }
  } else {
    "Invalid Histology Status. Exiting"
  }
}

Code Snippets

get_treatment_rec <- function(Histology, ER, PR, HER2, PrimaryTumor, TumorSize, NearbyLymphNode, Metastasis, Stage) {
  foo <- NearbyLymphNode %in% c("N0", "N1") && PrimaryTumor %in% c("T1", "T2", "T3")

  if (Histology %in% c("ductal", "lobular", "mixed", "metaplastic")) {
    if (ER || PR) {
      if (HER2) {
        if (foo) {
          if (TumorSize <= 0.5) {
            if (NearbyLymphNode == "N0") {
              "Consider adjuvant endocrine therapy and/or adjuvant chemotherapy with Trastuzumab"
            } else if (NearbyLymphNode == "N1") {
              "Adjuvant endocrine therapy or adjuvant chemotherapy with Trastuzumab followed by endocrine therapy"
            }
          } else if (TumorSize > 0.06 & TumorSize < 1.0) {
            "Adjuvant endocrine therapy and/or adjuvant chemotherapy with Trastuzumab"
          } else {
            "Adjuvant endocrine therapy and adjuvant chemotherapy with Trastuzumab"
          }
        }
      } else {
        if (foo) {
          if (TumorSize <= 0.5) {
            if (NearbyLymphNode == "N0") {
              "Consider adjuvant endocrine therapy"
            }
            if (NearbyLymphNode == "N1") {
              "Adjuvant endocrine therapy and/or adjuvant chemotherapy"
            }
          } else {
            "Consider 21-gene RT-PCR assay"
          }
        }
      }
    } else if (!ER && !PR) {
      if (HER2) {
        if (foo) {
          if (TumorSize <= 0.5) {
            if (NearbyLymphNode == "N0" || NearbyLymphNode == "N1") {
              "Consider adjuvant chemotherapy with Trastuzumab"
            }
          } else if (TumorSize > 0.06 & TumorSize < 1.0) {
            "Consider adjuvant chemotherapy with Trastuzumab"
          } else {
            "Adjuvant chemotherapy with Trastuzumab"
          }
        }
      } else if (!HER2) {
        if (foo) {
          if (TumorSize <= 0.5) {
            if (NearbyLymphNode == "N0") {
              "No adjuvant therapy"
            } else if (NearbyLymphNode == "N1") {
              "Consider adjuvant chemotherapy"
            }
          } else if (TumorSize > 0.06 & TumorSize < 1.0) {
            "Consider adjuvant chemotherapy"
          } else {
            "Adjuvant chemotherapy"
          }
        }
      } else {
        "Invalid HER2 Status. Exiting."
      }
    }
  } else if (Histology %in% c("tubular", "mucinous")) {
    if (ER || PR) {
      if (foo) {
        if (TumorSize <= 1) {
          "No adjuvant therapy"
        } else if (TumorSize > 1 && TumorSize < 3) {
          "Consider adjuvant endocrine therapy"
        } else {
          "Adjuvant endocrine therapy"
        }
      }
    } else if (!ER || !PR) {
      "Repeat determination of ER/PR status"
    }
  } else {
    "Invalid Histology Status. Exiting"
  }
}

Context

StackExchange Code Review Q#125442, answer score: 2

Revisions (0)

No revisions yet.