0

Say we have a column in a df that is contains mostly numeric values, but a few rows are character:

row1 <- c(2, 3, 5, 1, 0) 
row2 <- c(5, 2, "char", "word", 10) 
df <- data.frame(row1, row2) 
> df
row1  row2
2      5
5      char
1      word
3      2
0      10

How can I remove rows in the entire df that contain a character in row2, such that the final df should look like this:

> df
row1  row2
2      5
3      2
0      10
markus
  • 25,843
  • 5
  • 39
  • 58
juanjedi
  • 140
  • 1
  • 7
  • Related: [Check if string contains ONLY NUMBERS or ONLY CHARACTERS (R)](https://stackoverflow.com/questions/43195519/check-if-string-contains-only-numbers-or-only-characters-r) – markus Nov 24 '21 at 21:22

3 Answers3

1

Try this:

df[!is.na(as.numeric(as.character(df$row2))),]  


df[!is.na(as.numeric(df$row2)),]  

Edited: Add solution without as.character (following @markus comment)

Bloxx
  • 1,495
  • 1
  • 9
  • 21
1
library(tidyverse)
df |>
  filter(!is.na(as.numeric(row2)))
deschen
  • 10,012
  • 3
  • 27
  • 50
  • 2
    isn't it a little bit excessive to load the entire tidyverse just for the filter function? :D – mnist Nov 24 '21 at 21:10
  • 1
    If you only open R to run these two lines of code, maybe. But I would assume that‘s hardly ever the case. – deschen Nov 24 '21 at 21:21
1

I just wanted to provide a fuller answer here so you can understand how to solve this issue.

Using your vector row2, we can coerce that data from character type to numeric type using the as.numeric() function. R will do the best it can — it's easy to coerce "2" or "5" to numbers, but R won't know what to do with "word" or "char" so it will return NAs.

as.numeric(row2)

The is.na() function can then return a logical vector saying whether each of those elements is an NA value.

is.na(as.numeric(row2))

That logic can be reversed by adding a ! as a prefix.

!is.na(as.numeric(row2))

Finally, that logical vector can be used to subset a data structure.

row2[!is.na(as.numeric(row2))]
df[!is.na(as.numeric(df$row2)), ]
rg255
  • 4,119
  • 3
  • 22
  • 40