R如何遍历data.frame中的所有字符变量并更改特定值

时间:2018-07-15 20:49:58

标签: r loops dataframe dplyr lapply

我试图遍历data.table中的所有变量并修改所有字符变量;这些字符变量的某些值为“ NULL”,我想将其更改为“”。

例如:我要更改

    library(data.table)
    df <- data.table('id' = seq(1:10),
             'datadate' = seq(as.Date('2015-01-01'), as.Date('2015-01-10'), by="days"),
             'charvar' = c('a', 'b', 'c', rep('NULL', 7)),
             'charvar1' = c('a', 'b', 'c', 'd', rep('NULL', 6)))



    id   datadate charvar charvar1
 1:  1 2015-01-01       a        a
 2:  2 2015-01-02       b        b
 3:  3 2015-01-03       c        c
 4:  4 2015-01-04    NULL        d
 5:  5 2015-01-05    NULL     NULL
 6:  6 2015-01-06    NULL     NULL
 7:  7 2015-01-07    NULL     NULL
 8:  8 2015-01-08    NULL     NULL
 9:  9 2015-01-09    NULL     NULL
10: 10 2015-01-10    NULL     NULL

进入

    id   datadate charvar charvar1
 1:  1 2015-01-01       a        a
 2:  2 2015-01-02       b        b
 3:  3 2015-01-03       c        c
 4:  4 2015-01-04                d
 5:  5 2015-01-05                 
 6:  6 2015-01-06                 
 7:  7 2015-01-07                 
 8:  8 2015-01-08                 
 9:  9 2015-01-09                 
10: 10 2015-01-10                 

我尝试了两种方法:

第一种方法:

    df %>%
      mutate_if(is.character(.)==TRUE, 
                funs(function(col){col = if_else(col=='NULL', '', col)})) 
出现错误的

          Error: length(.p) == length(vars) is not TRUE

第二种方法:

data.frame(
  lapply(df, function(col)
              {if(is.character(col)==TRUE) col = ifelse(col=='NULL', '', col)})
)

我得到了错误

Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,  : 
  arguments imply differing number of rows: 0, 10

我在这里做错了什么?希望能对如何纠正这两种方法以及上面的代码为什么出错有深刻的见解。

1 个答案:

答案 0 :(得分:1)

由于dfdata.table,因此可以通过在[.data.table中向i提供逻辑向量并在j中分配新值来修改特定行例如df[charvar == 'NULL', charvar := '']。因此,您可以lapply遍历所有字符列以针对每个字符列执行此操作。这样可以避免使用ifelse,从而避免每次都重新分配整个列。

library(data.table)

lapply(names(df)[sapply(df, is.character)], #lapply over all character column names
       function(x) df[df[[x]] == 'NULL', (x) := '']) #set column equal to '' for rows where it equals 'NULL'

如果您想使用dplyr,可以这样做

library(dplyr)

df %>%
  mutate_if(is.character, 
            function(col) if_else(col == 'NULL', '', col))

tidyverse中(在一定程度上是一致的),.代表管道%>%的左侧。因此,如果您使用is.character(.)作为第一个参数,则dplyr将计算is.character(df),即FALSE,长度为1的逻辑向量。但是mutate_if期望一个长度为ncol(df)的逻辑矢量或一个函数。

具有1个字符列的示例数据。

df <- data.table('id' = seq(1:10),
                 'datadate' = seq(as.Date('2015-01-01'), as.Date('2015-01-10'), by="days"),
                 'charvar' = c('a', 'b', 'c', rep('NULL', 7)),
                 'charvar2' = sample(c('a', 'b', 'c', rep('NULL', 7))) )