0

I need to detect if my first row of observations is a row of names. Always when I import the data are imported as character columns from the spreasheet (readxl package).

By the structure of the data, a non-name row, always contain at least 8 numeric values.

rowNoName <- c("23-234", "Bank of Wisdom", 1:8)
rowName <- c("code of acc", "name of acc", "ac", "li", "ui", "op", "o", "p", " e", "i")

So, in this logic, I use the implicit coercion to do my task. From a character element that is originally a numeric class element, the coercion is simple. But from an element that is originally a text string, the implicit coercion fails and throw a NA. The rule is:

testName <- function(row) {
if (sum(!is.na(as.numeric(row))) >= 8) {
  print("row without names")
} else {
  print("row with names")
}

This function solve the problem but exist another more formal way to do this? I mean, to avoid the warning message of the coercion in the output.

> testName(row)
[1] "row with names"
Warning message:
In testName(row) : NAs introduced by coercion
zx8754
  • 52,746
  • 12
  • 114
  • 209
Cristóbal Alcázar
  • 1,153
  • 14
  • 26

1 Answers1

3

Test cases:

rowNoName <- c("23-234", "Bank of Wisdom", 1:8)
rowName <- c("code of acc", "name of acc", 
   "ac", "li", "ui", "op", "o", "p", " e", "i")

Your approach:

testName0 <- function(row) {
   sum(!is.na(as.numeric(row)))>=8
}
testName0(rowNoName)
testName0(rowName)

The simplest way to do this is to simply wrap the condition in suppressWarnings():

testName1 <- function(row) {
   suppressWarnings(sum(!is.na(as.numeric(row)))>=8)
}
testName1(rowNoName) 
testName1(rowName)

suppressWarnings() suppresses all warnings, unfortunately, and as far as I know there is no simple way to filter on a particular warning: warnings in R do not have associated unique codes, and warning texts may be translated to other languages ...). For example, if for some crazy reason you ended up with row being set to a complex number, e.g. sum(!is.na(as.numeric(2+3i))) would give the warning "imaginary parts discarded in coercion", but this warning would be suppressed even though you probably would have wanted to see it.

Therefore, an alternative approach, which more specifically detects what you're interested in, would be:

testName2 <- function(row) {
  sum(grepl("^[0-9]+$",row)) >=8
}
testName2(rowNoName)
testName2(rowName)

This assumes by "numbers" you mean "integers". If you want to detect floating point numbers, you would need a different/more complex regular expression.

More generally you might want to write these functions as testNamex <- function(row,min_nums=8) { ... }

Ben Bolker
  • 211,554
  • 25
  • 370
  • 453
  • I tried to use regex as different approach in match the names, but didn't ocurr to me to apply in the condition itself. – Cristóbal Alcázar Nov 04 '16 at 19:05
  • While the sentiment is appreciated, StackOverflow deprecates [using comments to say "thank you"](http://meta.stackoverflow.com/questions/258004/should-thank-you-comments-be-flagged?lq=1); if this answer was useful you can upvote it (if you have sufficient reputation), and in any case if it answers your question satisfactorily you are encouraged to click the check-mark to accept it. – Ben Bolker Nov 04 '16 at 19:05
  • Copy that; In the case of `suppressWarnings`, if the function that provoke the warnings is segregated from the main "program", encapsulate the `suppressWarnings`, and then call it from the main program the warnings didn't appear without suppreses posibles other warnings? – Cristóbal Alcázar Nov 04 '16 at 19:15
  • not sure what your question means. `suppressWarnings()` only suppresses warnings from the statements it wraps. (If you really wanted to suppress *all* warnings, use `options(warn=-1)`) – Ben Bolker Nov 04 '16 at 19:21