从 R 中的整个数据帧中删除空格

Posted

技术标签:

【中文标题】从 R 中的整个数据帧中删除空格【英文标题】:Removing Whitespace From a Whole Data Frame in R 【发布时间】:2014-01-12 16:13:18 【问题描述】:

我一直在尝试删除数据框中的空白(使用 R)。数据框很大 (>1gb) 并且有多个列,每个数据条目中都包含空格。

有没有一种快速的方法可以从整个数据框中删除空白?我一直在尝试对前 10 行数据的子集执行此操作:

gsub( " ", "", mydata) 

这似乎不起作用,尽管 R 返回了一个我无法解释的输出。

str_replace( " ", "", mydata)

R 返回 47 条警告,并且没有删除空格。

erase_all(mydata, " ")

R 返回一个错误说'错误:找不到函数“erase_all”'

在过去 24 小时里我一直在努力解决这个问题,因此我非常感谢您提供帮助。

谢谢!

【问题讨论】:

mydata[mydata == " "] <- "" 查找所有" " 并在data.frame 中替换为""。简单来说,就是你想要的这样的东西吗? 您应该将文件/数据的第一行添加到问题中。 我有一个具有这种格式的字符列:“A _ b”,我需要将其转换为“A_b”,但这些方法似乎不起作用。 @PKumar 【参考方案1】:

很多答案都比较老,所以在 2019 年这里有一个简单的 dplyr 解决方案,它只对字符列进行操作以删除尾随和前导空格。

library(dplyr)
library(stringr)

data %>%
  mutate_if(is.character, str_trim)

## ===== 2020 edit for dplyr (>= 1.0.0) =====
df %>% 
  mutate(across(where(is.character), str_trim))

如果您想要不同风格的空格删除,您可以将 str_trim() 函数切换为其他函数。

# for example, remove all spaces
df %>% 
  mutate(across(where(is.character), str_remove_all, pattern = fixed(" ")))

【讨论】:

如何将因子转换为字符串? 非常相似。查看?is.factor?as.character。这里的第二个答案显示了它。 ***.com/questions/2851015/… mutate(across(where(is.character), str_remove_all, pattern = fixed(" "))) 抛出错误。我相信这个想法是正确的,但语法是错误的。 @NewBee 很有趣。这个对我有用。我知道对齐所有 tidyverse 软件包版本有时可能是个问题。【参考方案2】:

如果我对您的理解正确,那么您想从整个数据框中删除所有空格,我猜您使用的代码很适合删除列名中的空格。我认为您应该试试这个:

 apply(myData,2,function(x)gsub('\\s+', '',x))

希望这行得通。

这将返回一个矩阵,但是,如果您想将其更改为数据框,请执行以下操作:

as.data.frame(apply(myData,2,function(x)gsub('\\s+', '',x)))

2020 年编辑:

lapplytrimws 函数与both=TRUE 一起使用可以删除前导和尾随空格,但不能删除其中的空格。由于OP 没有提供输入数据,因此我添加了一个虚拟示例来生成结果。

数据:

df <- data.frame(val = c(" abc"," kl m","dfsd "),val1 = c("klm ","gdfs","123"),num=1:3,num1=2:4,stringsAsFactors = FALSE)

#situation: 1(使用 Base R),当我们想要删除仅在开头和结尾而不是在字符串值内的空格时,我们可以使用 修剪

cols_to_be_rectified <- names(df)[vapply(df, is.character, logical(1))]
df[,cols_to_be_rectified] <- lapply(df[,cols_to_be_rectified], trimws)

# situation: 2 (Using Base R) ,当我们想要删除数据帧中字符列中每个位置的空格时(字符串内部以及前导和尾端)。

(这是使用 apply 提出的初始解决方案,请注意使用 apply 的解决方案似乎可以工作但会很慢,而且如果 OP 真的想删除前导/尾随,问题显然不是很清楚空白或数据中的每个空白)

cols_to_be_rectified <- names(df)[vapply(df, is.character, logical(1))]
df[,cols_to_be_rectified] <- lapply(df[,cols_to_be_rectified], function(x)gsub('\\s+','',x))

##情况:1(使用data.table,只删除前导和尾随空格)

library(data.table)
setDT(df)
cols_to_be_rectified <- names(df)[vapply(df, is.character, logical(1))]
df[,c(cols_to_be_rectified) := lapply(.SD, trimws), .SDcols = cols_to_be_rectified]

输出来自situation1

    val val1 num num1
1:  abc  klm   1    2
2: kl m gdfs   2    3
3: dfsd  123   3    4

## 情况:2(使用 data.table,删除里面的每个空格以及前导/尾随空格)

cols_to_be_rectified <- names(df)[vapply(df, is.character, logical(1))]
df[,c(cols_to_be_rectified) := lapply(.SD, function(x)gsub('\\s+', '', x)), .SDcols = cols_to_be_rectified]

输出来自situation2

    val val1 num num1
1:  abc  klm   1    2
2:  klm gdfs   2    3
3: dfsd  123   3    4

注意两种情况的输出之间的区别,在第 2 行:您可以看到,使用 trimws 我们可以删除前导和尾随空格,但使用正则表达式解决方案我们能够删除每个空格。

希望对你有帮助,谢谢

【讨论】:

感谢 Pradeep!所以当我在前几行运行它时,这似乎有效。然后当我尝试在整个数据集上运行它时,我的笔记本电脑在一段时间后放弃了,R 说它已经达到了内存限制。我将分析分解成更小的块的最佳方法是什么?我可以指定它一次只对数据矩阵中的单个列执行 gsub 函数吗? 对于这么大的数据文件,最好首先获取包ff。然后,您可以隐式地将文件分成几部分并避免内存限制。 @CarlWitthoft 您可以使用 ff 和 sed 查看我的答案。 @Pradeep 您的解决方案仅适用于每列都是“字符”的数据框。如果不是,则所有非字符列都转换为“字符” @MarkusN ,请理解这个问题,它说“在每个数据条目中包含空格的多列”,这意味着数据帧的每个元素都是字符。因此,基于这个假设,我提出了这个解决方案。这个解决方案在这个问题上运行良好。我从来没有写过它适用于所有情况。在否决任何答案之前,请先查看情况。这个答案在任何意义上都没有错/不好。另请阅读投票标准。还请理解,当 R 版本 【参考方案3】:

根据 Fremzy 和 Stamper 的评论,现在这是我清理数据中空白的便捷例程:

df <- data.frame(lapply(df, trimws), stringsAsFactors = FALSE)

正如其他人所指出的那样,这会将所有类型更改为字符。在我的工作中,我首先确定原始中可用的类型和所需的转换。修剪后,我重新应用所需的类型。

如果您的原始类型没问题,请在 https://***.com/a/37815274/2200542 下方应用 MarkusN 的解决方案

那些使用 Excel 文件的人可能希望探索 readxl 包,它在阅读时默认为 trim_ws = TRUE。

【讨论】:

我已经尝试过这个解决方案,但它会将所有列更改为因子。 使用df &lt;- data.frame(lapply(df, trimws), stringsAsFactors = FALSE)。 (我知道这个线程很旧,只是在这里为其他人注意。) 这个解决方案对我有用 - 并没有将列的类转换为因子。【参考方案4】:

参考了 Fremzy 和 Mielniczuk,我得出了以下解决方案:

data.frame(lapply(df, function(x) if(class(x)=="character") trimws(x) else(x)), stringsAsFactors=F)

它适用于混合数字/字符数据帧,仅操作字符列。

【讨论】:

更改列名内的所有空格 函数 data.frame() 默认检查并“更正”列名。如果您希望您的列名不受影响,请使用 data.frame(... , check.names=F) 这只是修剪空白,它不会删除内部空白,对吧?【参考方案5】:

仅涉及dplyr 的一种可能性是:

data %>%
 mutate_if(is.character, trimws)

或者考虑到所有变量都是类字符:

data %>%
 mutate_all(trimws)

由于dplyr 1.0.0(仅限字符串):

data %>%
 mutate(across(where(is.character), trimws))

或者如果所有列都是字符串:

data %>%
 mutate(across(everything(), trimws))

【讨论】:

【参考方案6】:

R 根本不适合这种文件大小。但是有两个选择:

使用 ffdply 和 ff base

使用ffffbase 包:

library(ff)
library(ffabse)
x <- read.csv.ffdf(file=your_file,header=TRUE, VERBOSE=TRUE,
                 first.rows=1e4, next.rows=5e4)
x$split = as.ff(rep(seq(splits),each=nrow(x)/splits))
ffdfdply( x, x$split , BATCHBYTES=0,function(myData)        
             apply(myData,2,function(x)gsub('\\s+', '',x))

使用 sed(我的偏好)

sed -ir "s/(\S)\s+(/S)/\1\2/g;s/^\s+//;s/\s+$//" your_file 

【讨论】:

【参考方案7】:

您可以在所有列上使用 R 3.2 中的 trimws 函数。

myData[,c(1)]=trimws(myData[,c(1)])

您可以对数据集中的所有列进行循环。它在处理大型数据集时也具有良好的性能。

【讨论】:

【参考方案8】:

如果您正在处理这样的大型数据集,您可以真正受益于data.table 的速度。

library(data.table)

setDT(df)

for (j in names(df)) set(df, j = j, value = df[[trimws(j)]]) 

我希望这是最快的解决方案。这行代码使用data.tableset 运算符,它非常快速地循环列。这里有一个很好的解释:Fast looping with set。

【讨论】:

此解决方案中存在拼写错误,以下将起作用: for (j in names(dat)) if(class(dat[[j]])=="character") set( dat, j = j, 值 = trimws(dat[[j]]) ) 【参考方案9】:

如果您想在data.frame 中维护变量类 - 您应该知道使用apply 会破坏它们,因为它会输出matrix,其中所有变量都转换为characternumeric。在 Fremzy 和 Anthony Simon Mielniczuk 的代码的基础上,您可以遍历 data.frame 的列,并仅从 factorcharacter 类的列中修剪空白(并维护您的数据类):

for (i in names(mydata)) 
  if(class(mydata[, i]) %in% c("factor", "character"))
    mydata[, i] <- trimws(mydata[, i])
  

【讨论】:

【参考方案10】:

我认为使用 sapply 的简单方法也可以,给定一个像这样的 df:

dat<-data.frame(S=LETTERS[1:10],
            M=LETTERS[11:20],
            X=c(rep("A:A",3),"?","A:A ",rep("G:G",5)),
            Y=c(rep("T:T",4),"T:T ",rep("C:C",5)),
            Z=c(rep("T:T",4),"T:T ",rep("C:C",5)),
            N=c(1:3,'4 ','5 ',6:10),
            stringsAsFactors = FALSE)

你会注意到 dat$N 将成为类字符,因为 '4 ' &amp; '5 ' (你可以检查 class(dat$N)

要去除数字列上的空格,只需使用as.numericas.integer 转换为numeric

dat$N&lt;-as.numeric(dat$N)

如果要删除所有空格,请执行以下操作:

dat.b<-as.data.frame(sapply(dat,trimws),stringsAsFactors = FALSE)

再次在 col N 上使用 as.numeric(因为 sapply 会将其转换为 character

dat.b$N<-as.numeric(dat.b$N)

【讨论】:

以上是关于从 R 中的整个数据帧中删除空格的主要内容,如果未能解决你的问题,请参考以下文章

r 从数据帧中删除NA并替换为0

从SPSS导入时如何从R中的数据框中删除空格

组合2个字符串的最快方法,将字符串从第二列交错到整个数据帧中的第一列

如何删除数据帧中的间隔之间的值

R:从一个数据帧中提取行,基于列名匹配来自另一个数据帧的值

如何将字符串输入(带空格的数字)转换为Shiny(R)中的数据帧?