如何在数据框的特定列中替换字符。

3

我有一个数据框,想要清理那些包含字符价格的列。我想去掉美元符号和逗号分隔符,并将这些列转换为数字类型。

structure(list(Sold.Price = c("", "$177,500", "$180,000", "$180,000", 
"$189,000"), Title.to.Land = c("Freehold Strata", "Freehold Strata", 
"Freehold Strata", "Freehold Strata", "Freehold Strata"), Price = c("$174,900", 
"$177,500", "$180,000", "$180,000", "$189,000"), DOM = c(93L, 
34L, 39L, 56L, 2L), List.Date = c("10/4/2019", "12/12/2019", 
"12/9/2019", "11/12/2019", "1/9/2020"), MaintFee = c("$2,916.00", 
"$373.80", "$331.57", "$320.42", "$1,055.67")), row.names = c(NA, 
5L), class = "data.frame")

  Sold.Price   Title.to.Land    Price DOM  List.Date  MaintFee
1            Freehold Strata $174,900  93  10/4/2019 $2,916.00
2   $177,500 Freehold Strata $177,500  34 12/12/2019   $373.80
3   $180,000 Freehold Strata $180,000  39  12/9/2019   $331.57
4   $180,000 Freehold Strata $180,000  56 11/12/2019   $320.42
5   $189,000 Freehold Strata $189,000   2   1/9/2020 $1,055.67

我尝试了这种方法:

combined_csv$Sold.Price <- gsub("\\$", "", combined_csv$Sold.Price)
combined_csv$Sold.Price <- gsub("\\,", "", combined_csv$Sold.Price)
combined_csv$Sold.Price <- as.numeric(combined_csv$Sold.Price)

但这看起来并不聪明。我希望能在一行中完成所有价格类型列(Sold.price,Maintfee等)的操作。我该如何做到?


1
使用正则表达式替换 \\D* - AnilGoyal
@AnilGoyal 你的意思是 combined_csv$Sold.Price <- gsub("\\D", "", combined_csv$Sold.Price) 吗?但即使我这样做了,我有多个列,我应该逐一为每个列进行操作。我想找到一种方法,首先列出我想要更改的列的名称,然后一次性进行更改。 - Ross_you
1
在这种情况下,可以在dplyr中使用mutate和across。 - AnilGoyal
@AnilGoyal,顺便说一下,\\D*不起作用,因为它会将33.4这样的数字中的.删除,并将其更改为334,这是错误的。 - Ross_you
4个回答

5
我认为您可以使用以下解决方案:
library(dplyr)

df %>%
  mutate(across(c(Sold.Price, Price, MaintFee), ~ as.numeric(gsub("[$,]", "", .x))))

  Sold.Price   Title.to.Land  Price DOM  List.Date MaintFee
1         NA Freehold Strata 174900  93  10/4/2019  2916.00
2     177500 Freehold Strata 177500  34 12/12/2019   373.80
3     180000 Freehold Strata 180000  39  12/9/2019   331.57
4     180000 Freehold Strata 180000  56 11/12/2019   320.42
5     189000 Freehold Strata 189000   2   1/9/2020  1055.67

或者在 R 基础中,我们可以这样做:

as.data.frame(sapply(df, function(x) {
  if(any(grepl("\\$", x))) {
    as.numeric(gsub("[$,]", "", x))
  } else {
    x
  }
}))

谢谢,奇怪的是这段代码对我来说不起作用,仍然显示之前的样式。我还尝试过:a <- a %>% mutate(across(c(Sold.Price, Price, MaintFee), ~gsub("\\$", "", .) %>% as.numeric))但这也不起作用。 - Ross_you
一定有原因。代码不起作用是不可能的,因为这里没有发生任何特定的事情。请仔细检查您的数据,或者可能更新您的 dplyr(这很不可能导致此错误)。 - Anoushiravan R
没事,只要你需要帮忙就检查一下并告诉我。有时候我自己会忽略非常基本/显而易见的事情。我很乐意帮助每个人,特别是我的同胞们 :) - Anoushiravan R
1
@Anoushirvan R,正如TarJae在下面提到的那样,我只是将mutate更改为dplyr :: mutate,然后它就起作用了!我很惊讶,因为我已经使用library函数加载了dplyr。不确定为什么会发生这种情况。 - Ross_you
1
是的,我认为你已经附加了 plyr 包。现在我使用 plyr::mutate 但什么也没有改变。我还添加了一个基本的 R 解决方案。 - Anoushiravan R
显示剩余3条评论

4
我们可以使用 readr 包中的 parse_number(这将放弃第一个数字之前或之后的任何非数字字符)和 across 进行组合:
library(dplyr)
library(readr)
df %>%
  dplyr::mutate(across(c(Sold.Price, Price, MaintFee), parse_number))

 Sold.Price   Title.to.Land  Price DOM  List.Date MaintFee
1         NA Freehold Strata 174900  93  10/4/2019  2916.00
2     177500 Freehold Strata 177500  34 12/12/2019   373.80
3     180000 Freehold Strata 180000  39  12/9/2019   331.57
4     180000 Freehold Strata 180000  56 11/12/2019   320.42
5     189000 Freehold Strata 189000   2   1/9/2020  1055.67

不幸的是,就像@Anoushirvan R提供的解决方案一样,这段代码对我来说不起作用,并返回与原始数据框相同的数据框。肯定是我的问题出了问题,但不确定是什么问题。您的解决方案在我看来是有效的。 - Ross_you
1
dplyr::mutate 替换 mutate - TarJae
真奇怪!它起作用了!!我已经使用 library(dplyr) 加载了 dplyr,不确定出了什么问题。 - Ross_you
哈哈。@Roozbeh_you:输入 (.packages())(显示所有已加载的包),我确定 plyr 在列表中。 - TarJae
是的! plyr 是列表中的第一个!这是什么意思?是 plyr 导致了所有这些问题吗? - Ross_you
这里是解释:http://krlmlr.github.io/pdlyr/vignettes/pdlyr.html - TarJae

2

带有 currency 选项

library(dplyr)
library(formattable)
library(stringr)
df1 %>% 
    mutate(across(where(~ any(str_detect(., fixed("$")))), 
           ~ as.numeric(currency(.))))

-输出

 Sold.Price   Title.to.Land  Price DOM  List.Date MaintFee
1         NA Freehold Strata 174900  93  10/4/2019  2916.00
2     177500 Freehold Strata 177500  34 12/12/2019   373.80
3     180000 Freehold Strata 180000  39  12/9/2019   331.57
4     180000 Freehold Strata 180000  56 11/12/2019   320.42
5     189000 Freehold Strata 189000   2   1/9/2020  1055.67

2

一种可选的方法:

library(tidyverse)

df %>%
    dplyr::mutate(across(contains(c("Price","Fee")),~readr::parse_number(.x)))

  Sold.Price   Title.to.Land  Price DOM  List.Date MaintFee
1         NA Freehold Strata 174900  93  10/4/2019  2916.00
2     177500 Freehold Strata 177500  34 12/12/2019   373.80
3     180000 Freehold Strata 180000  39  12/9/2019   331.57
4     180000 Freehold Strata 180000  56 11/12/2019   320.42
5     189000 Freehold Strata 189000   2   1/9/2020  1055.67

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接