【问题标题】:Multiple sub() criteria over multiple columns多个列上的多个 sub() 条件
【发布时间】:2017-01-31 01:59:03
【问题描述】:

我正在尝试使用 sub() 执行查找和替换,并将其应用于多个列。

我的数据集如下所示:

> mydata
  col1      col2     col3        col4
1    1     $1.40    $5.39      $23.42
2    2   $(2.40) $(38.29) $(1,239.30)
3    3 $1,302.00  $102.32      $23.10

有几个以传统会计格式表示的数字字段。

我尝试编写以下函数来交换括号否定、千位分隔符和美元数字。

find_replace <- function(df, cols){
  df[, cols] <- sub('\\,','',df[, cols])
  df[, cols] <- sub('\\$','',df[, cols])
  df[, cols] <- sub('\\-','',df[, cols])
  df[, cols] <- sub('\\(','-',df[, cols])
  df[, cols] <- sub('\\)','',df[, cols])
  df[, cols] <- as.numeric(df[, cols])
}

mydata[,2:4] <- lapply(mydata[,2:4], find_replace(mydata, 2:4))

...但是当我在上面的数据帧上测试它时不断收到以下错误

Error in match.fun(FUN) : 
  'find_replace(mydata, 2:4)' is not a function, character or symbol

当我尝试在我的实际数据集上运行它时(将它应用于 6 列和大约 480 万行),它会挂起并且必须在我收到错误之前停止操作,但我想它是一样的。

对于所有字段都是数字的有效方法有什么建议吗?在读取类似于this 方法但没有成功的csv 时,我也尝试使用带有SetClass 函数的colClass 参数。

> mydata
  col1    col2   col3     col4
1    1    1.40   5.39    23.42
2    2   -2.40  38.29 -1239.30
3    3 1302.00 102.32    23.10

提前谢谢你!

编辑:再次尝试 setClass 选项,并使用来自@waterling 的正则表达式:

setClass("acntngFmt")
# [1] "acntngFmt"
setAs("character", "acntngFmt",
      function(from) as.numeric(gsub("(?![.])[[:punct:]]", "", col, perl=TRUE, from)))

Input <- "A, B, C
$1.40, $(2.40), $1,302.00
$5.39, $(38.29), $102.32
$23.42, $(1,239.30), $23.10"

DF <- read.csv(textConnection(Input), header = TRUE,
               colClasses = c("acntngFmt", "acntngFmt", "acntngFmt"))
Error in as.character(x) : 
  cannot coerce type 'closure' to vector of type 'character' 

【问题讨论】:

标签: r


【解决方案1】:
df<-data.frame(V1=c("$1.40","$(2.40)","$(1,302.00)"), V2=c("$5.39","$(38.29)","$0.00"))
           V1       V2
1       $1.40    $5.39
2     $(2.40) $(38.29)
3 $(1,302.00)    $0.00

apply(df, 2, function(col) as.numeric(gsub("(?![.])[[:punct:]]", "", col, perl=TRUE)))
         V1    V2
[1,]    1.4  5.39
[2,]    2.4 38.29
[3,] 1302.0  0.00

已编辑

apply(df, 2, function(col) {
  as.numeric(
    gsub("\\((.*)\\)","-\\1", 
         gsub("(?![.\\(\\)])[[:punct:]]", "", col, perl=TRUE)
         )
  )
})

 V1     V2
[1,]     1.4   5.39
[2,]    -2.4 -38.29
[3,] -1302.0   0.00

【讨论】:

  • 似乎您可以通过改进正则表达式部分来使其工作?您将如何编辑它以包括将“$(2.40)”替换为 -2.40?括号表示负数。
【解决方案2】:

这首先将前括号转换为减号,然后删除所有逗号、右括号和美元符号。

setClass("acntngFmt")

setAs("character", "acntngFmt",
    function(from) as.numeric( gsub("[$),]", "", gsub("\\(", "-", from))))
DF <- data.frame( lapply(mydata[2:4], as, "acntngFmt"))
#---------------
 DF
    col2   col3     col4
1    1.4   5.39    23.42
2   -2.4 -38.29 -1239.30
3 1302.0 102.32    23.10

而不是使用 colClasses,这只是在字符分类列上使用通用as-函数。如果您的列是因子类,您首先需要转换为字符。

mydata <- 
structure(list(col1 = 1:3, col2 = structure(c(3L, 1L, 2L), .Label = c("$(2.40)", 
"$1,302.00", "$1.40"), class = "factor"), col3 = structure(c(3L, 
1L, 2L), .Label = c("$(38.29)", "$102.32", "$5.39"), class = "factor"), 
    col4 = structure(c(3L, 1L, 2L), .Label = c("$(1,239.30)", 
    "$23.10", "$23.42"), class = "factor")), .Names = c("col1", 
"col2", "col3", "col4"), class = "data.frame", row.names = c("1", 
"2", "3"))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-01
    • 2022-11-30
    • 1970-01-01
    • 1970-01-01
    • 2017-10-08
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多