如何删除 r 数据框中多个定义列中的特定字符?
我有一个数据集需要认真清理,类似于下面的示例数据。我的最终目标是拥有一个数据帧,其中列类型与列名称匹配(例如,日期 = 日期、时间 = 时间、数字 1 = 数字、字符 = 字符),并且其中所有特殊字符或值否则会阻止删除到正确类型的转换。真实的数据集包含超过 60 列,其中大约一半需要删除多个字符,因此我想找到一种方法来选择适当的列以进行多次修改,并尽可能减少代码重复。
如有任何帮助,我们将不胜感激。
#Example Data Input from nested list
my_nested_list <- list(date=c('8/16/2010', '8/17/2010', '8/18/201', '8/19/2010', '8/20/2010'),
times=c('8:45', '14:20', '13:00', '15:20', '9:05'),
numeric1=c('>3.0','> 3.0','1.2m','.8','1.8'),
char=c('Epi', '', 'Hypo', 'Epi', '', ''),
numeric2=c('N/A', '-', '8.9', '', '2.2'),
numeric3=c('R', '12.4', '4.1', '', '11.58'))
#Convert nested list to the dataframe by columns
df <- as.data.frame(do.call(cbind, my_nested_list))
df
sapply(df, class) #displays all column types as characters
我知道您可以使用 str_replace_all() 或 gsub() 来替换一列或所有列中的特殊字符,但我想在指定列中执行此操作(例如 df$numeric1、df$numeric2、df$numeric3或 df[3]、df[5:6])。如示例数据中所示,我也有非特殊字符,只需从数字列中删除(例如“R”、“">”、“>”、“m”、“-”、“N/A” ”)
这就是我替换特殊字符和每个单独字符的方式,一次一列,但我对想法持开放态度。我也尝试过做多个列,但它不起作用。
#One column at a time
##Using str_replace_all() in one specified column
df$numeric1 <- str_replace_all(df$numeric1, "\[\[:punct:\]\]", " ")
df$numeric1 <- str_replace_all(df$numeric1, ""R", " ")
##Using base gsub() in one specified column
gsub("\[\[:punct:\]\]", " ", df$numeric1)
gsub("R", " ", df$numeric1)
#One character in multiple columns with resulting error: "Error in `[.default`(df, cols_nan) : invalid subscript type 'list'"
cols_nan <- c(df[5:6])
df[cols_nan] <- gsub('[^[:alnum:] ]','',df[cols_nan])
我尝试了几种方法来更改日期和时间列类型(根据之前的 stackoverflow 帖子)。当他们更改列类型时,他们在列中没有返回任何值。
#dates
df$date <- lubridate::mdy(df$date)
df$date <- as.Date(df$date, format= %Y-%m-%d")
df$date <- lubridate::mdy(df$date)
#time
df[['times']] <- strptime(df[['times']], format = "%H:%M:%S")
每次修改一个字符和一列时,列类型将使用以下方式更改。
df <-data.frame(df, stringsAsFactors=FALSE)
sapply(df, class) #I would like to display all column types as designated in headers
看起来你想要这样的东西:
pacman::p_load(tidyverse, hms)
df |> mutate(across(starts_with("num"), parse_number),
across(starts_with("times"), parse_hm),
across(starts_with("date"), ~ as.Date(.x, "%m/%d/%Y")),
across(starts_with("char"), ~ ifelse(.x == "", NA_character_, .x)))
输出:
# A tibble: 6 × 6
date times numeric1 char numeric2 numeric3
<date> <time> <dbl> <chr> <dbl> <dbl>
1 2010-08-16 08:45 3 Epi NA NA
2 2010-08-17 14:20 3 NA NA 12.4
3 0201-08-18 13:00 1.2 Hypo 8.9 4.1
4 2010-08-19 15:20 0.8 Epi NA NA
5 2010-08-20 09:05 1.8 NA 2.2 11.6
6 2010-08-16 08:45 3 NA NA NA