从 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 年编辑:
将lapply
和trimws
函数与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 <- 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
使用ff
和ffbase
包:
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.table
的set
运算符,它非常快速地循环列。这里有一个很好的解释: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
,其中所有变量都转换为character
或numeric
。在 Fremzy 和 Anthony Simon Mielniczuk 的代码的基础上,您可以遍历 data.frame 的列,并仅从 factor
或 character
类的列中修剪空白(并维护您的数据类):
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 ' & '5 '
(你可以检查 class(dat$N)
)
要去除数字列上的空格,只需使用as.numeric
或as.integer
转换为numeric
。
dat$N<-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 中的整个数据帧中删除空格的主要内容,如果未能解决你的问题,请参考以下文章