删除r Dataframe 中多个已定义列中的特定和特殊字符

9jyewag0  于 2023-09-27  发布在  其他
关注(0)|答案(1)|浏览(79)

如何在r Dataframe 中删除多个定义列中的特定和特殊字符?
我有一个数据集,需要一些严重的清理,类似于下面的示例数据。我的最终目标是有一个 Dataframe ,其中列类型与列名匹配(例如,date = date,times = time,numeric 1 = numeric,char = character),并且删除了所有可能会阻止转换为正确类型的特殊字符或值。真实的数据集包含60多个列,其中大约一半需要删除多个字符,因此我想找到一种方法来选择适当的列,以尽可能少的代码重复进行多次修改。
请参见下面的示例数据输入和所需输出。根据要求,此图像显示the desired output dataframe appearance.
如果你能帮忙的话,我将不胜感激。

#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'),
                       character1=c('Epi', '', 'Hypo', 'Epi', ''),
                       character2=c('GC1238', '', 'GC1239', '', 'GC1240'),
                       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
siv3szwd

siv3szwd1#

似乎你想要这样的东西:

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

备注:
1.我对数据框中的每个列类型都使用了across(),假设在更大的数据框中,对于示例数据框中只有一列的数据框,将有多个列。此外,如果列的名称不一致,就像你的例子一样,你可以使用不同的方法来选择列-有很多方法,太多了,在这里无法列出,但是你可以询问我对真实的数据的建议,或者查看文档。

  1. cols_nan <- c(df[5:6])从dataframe中获取实际的第五列和第六列。然后尝试基于该列对 Dataframe 进行索引,但由于该列是一个列表,因此会失败。您可能需要gsub('[^[:alnum:] ]','',df[5:6])(但即使这样也会产生一个不好的结果)。
    1.我给出的输出的一个问题是第三个日期的年份值。我保持不变,因为A。对你来说很容易修好,但是最好因为我不想创建一个修复程序,它只对那个行有效,但对真实的数据集中的许多其他行无效(甚至破坏)。如果您提供更多错误日期行的示例,那么我将能够提供更多帮助。
  2. re:"\[\[:punct:\]\]"-在R的正则表达式中需要转义两次-即应该是"\\[\\[:punct:\\]\\]"

相关问题