Удалить или заменить числовые значения в смешанном типе данных

#r

#r

Вопрос:

это кажется простым вопросом, и я провел некоторые поиски, но не могу найти очевидный ответ. У меня есть фрейм данных со смесью числовых значений и символов:

 df=data.frame(ID=c("S1","S2","S3","S4","S5"),
              V1=c("0.3","A","A","0.6","C"),
              V2=c("C","A","0.7","B","0.2"),
              V3=c("0.2","B","0.7","C","C"),stringsAsFactors=F)
tibble(df)

  ID    V1    V2    V3   
  <chr> <chr> <chr> <chr>
1 S1    0.3   C     0.2  
2 S2    A     A     B    
3 S3    A     0.7   0.7  
4 S4    0.6   B     C    
5 S5    C     0.2   C 
 

По-видимому, все они имеют «символьный» тип, и я хочу добиться удаления или замены всех «числовых» элементов во фрейме данных на NA, чтобы идеальный результат был:

   ID    V1    V2    V3   
  <chr> <chr> <chr> <chr>
1 S1    NA    C     NA  
2 S2    A     A     B    
3 S3    A     NA    NA  
4 S4    NA    B     C    
5 S5    C     NA    C 

OR

  ID    V1    V2    V3   
  <chr> <chr> <chr> <chr>
1 S1          C       
2 S2    A     A     B    
3 S3    A          
4 S4          B     C    
5 S5    C           C 
 

Надеюсь, это имеет смысл. Большое спасибо за помощь!

Ответ №1:

Создайте функцию num2na, которая использует type.convert затем проверяет, преобразовано ли оно в числовое. Vectorize(num2na) создает функцию, которая может работать с вектором, и мы применяем ее к каждому столбцу, превращая результирующий список обратно во фрейм данных с помощью replace . Пакеты не используются.

 num2na <- function(x) if (is.numeric(type.convert(x))) NA else x
replace(df, TRUE, lapply(df, Vectorize(num2na)))
 

предоставление:

   ID   V1   V2   V3
1 S1 <NA>    C <NA>
2 S2    A    A    B
3 S3    A <NA> <NA>
4 S4 <NA>    B    C
5 S5    C <NA>    C
 

Комментарии:

1. df[] = apply(df, c(1,2), num2na) немного проще

2. @Columbo, но он перезаписывает входные данные, что, в общем, нежелательно.

Ответ №2:

Вы можете использовать шаблон регулярных '^\d (\.\d )?' выражений, чтобы найти значения, которые являются только числами, а затем применить dplyr::across его к каждому столбцу, чтобы заменить любое значение, удовлетворяющее этому шаблону NA .

 library(dplyr)
df %>% mutate(across(V1:V3, ~replace(.x, grepl('^\d (\.\d )?', .x), NA)))

#  ID   V1   V2   V3
#1 S1 <NA>    C <NA>
#2 S2    A    A    B
#3 S3    A <NA> <NA>
#4 S4 <NA>    B    C
#5 S5    C <NA>    C
 

Или с lapply помощью in base R :

 df[-1] <- lapply(df[-1], function(x) replace(x, grepl('^\d (\.\d )?', x), NA))
 

Комментарии:

1. Спасибо, но другой ответ работает немного лучше для меня. Я ценю помощь!