【问题标题】:Exchange Strings with Numbers in R用 R 中的数字交换字符串
【发布时间】:2022-01-12 14:43:34
【问题描述】:

我只是想知道 R 是否有办法将字符串向量转换为我定义的数字。例如,假设我们有一个向量如下:

vector <- c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC")

我想做的不是在向量中包含元素ABCDEFGHI,而是希望用用户定义的数字“交换”它们,这样而不是在向量中有ABC 我有1,而不是DEF 我有2,而不是GHI 我有3,所以向量现在变成了

vector <- c(1, 2, 3, 1, 3, 1)

我知道有些函数可以做与此类似的事情,但它们并不能完全满足我的要求。例如,函数as.numeric(as.factor()) 会将一个填充了字符串元素的向量转换为数字,这正是我想要的,但不幸的是它不允许我实际定义什么字符串值变成什么数字,这将是一个主要问题,当我正在使用更改的数据集,因为数字将代表不同的字符串。

另一种替代方法是使用chartr(old = "ABC", new = "123", x) 函数(其中x 是您的数据集),这也很好,但其背后的主要问题是“旧”字符的数量必须与“新”字符,而且字母的每个实例都将更改为一个数字,因此,如果我们将 ABC 替换为 123 ,那么每次出现 B 时,它将始终替换为 2不是我想要的。

R 是否有一个函数可以让我用用户定义的数字交换向量中的字符串?

编辑:特别是(对于希望将来这样做的任何人),我使用了以下函数:levels(vector)[levels(vector)=="ABC"] &lt;- "1" 这允许您将单个字符串因子级别与数值交换,反之亦然

【问题讨论】:

  • 使用factor并指定其levels
  • 这正是我需要的!谢谢,您能否将其放入回复中,以便我接受它作为答案?
  • 特别是(对于希望将来这样做的任何人),我使用了以下函数:levels(vector)[levels(vector)=="ABC"] &lt;- "1" 这允许您将单个字符串因子级别与数值交换,反之亦然跨度>
  • @ThePlowKing - 不需要一一做,只需:as.numeric(factor(vector, levels=c("ABC","DEF","GHI"))) 应该做。或者c(9,6,3)[factor(vector, levels=c("ABC","DEF","GHI"))],如果你想要你选择的完全任意的数值,不必是连续的。
  • 我意识到我上面评论中的第一段代码本质上是as.numeric(factor()) - 不同之处在于您可以重新排列levels= 以明确更改顺序。

标签: r string vector


【解决方案1】:
vector <- c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC")
vector
#[1] "ABC" "DEF" "GHI" "ABC" "GHI" "ABC"
vector=as.factor(vector)
vector
#[1] ABC DEF GHI ABC GHI ABC

vector=as.numeric(vector)
vector
#[1] 1 2 3 1 3 1

Try it Online

替代解决方案:

将字符串映射到用户定义的数字

    #map strings to numbers
    numbers <- c(1,2,3)
    names <- c("ABC", "DEF", "GHI") 

    #store maping in data frame
    df <- data.frame(names, numbers)
    df

     vector <-as.vector(  c("ABC", "DEF", "GHI", "ABC", "GHI", "ABC"))

     vector2=c() # the numeric vector
     for (i in 1:length(vector)){
     id <= which(df$names == vector[i])
     vector2 <= c(vector2 ,id)
     }
     print(vector2)
     #[1] 1 2 3 1 3 1

Try it online

【讨论】:

  • "as.numeric(as.factor()) ... 是我想要的,但不幸的是它不允许我实际定义什么字符串值变成什么数字 " - OP 特别声明他们想要的不是这个答案。
【解决方案2】:

1) 下标 这不使用任何包。如果您希望输出将原始字符串作为名称,请省略 unname

map <- c(ABC = 1, DEF = 2, GHI = 3)
unname(map[vector])
## [1] 1 2 3 1 3 1

2) 绑带

library(gsubfn)
strapply(vector, ".*", list(ABC = 1, DEF = 2, GHI = 3), simplify = TRUE)
## [1] 1 2 3 1 3 1

3) 因素 这不涉及任何包。

as.numeric(format(factor(vector, levels = c("ABC", "DEF", "GHI"), labels = 1:3)))
## [1] 1 2 3 1 3 1

或者如果数字始终为 1、2、...,则可以简化为:

as.numeric(factor(vector, levels = c("ABC", "DEF", "GHI")))
## [1] 1 2 3 1 3 1

如果您忽略levels=,那么它将按字母顺序将第一个分配给1,依此类推,因此如果该分配正常,那么它会进一步简化为:

as.numeric(factor(vector))
## [1] 1 2 3 1 3 1

4) 匹配 这也不使用任何包。

c(1, 2, 3)[match(vector, c("ABC", "DEF", "GHI"))]
## [1] 1 2 3 1 3 1

如果数字总是 1、2、...,那么可以简化为:

match(vector, c("ABC", "DEF", "GHI"))
## [1] 1 2 3 1 3 1

5) data.frame 这个适用于数据帧。前两行创建数据帧,nxxt 行进行查找,最后一行确保mDF 的顺序相同。如果顺序无关紧要,可以省略最后一行。这不使用任何包。

mapDF <- data.frame(let = c("ABC", "DEF", "GHI"), num = 1:3)
DF <- data.frame(let = vector, order = seq_along(vector))

m <- merge(DF, mapDF, all.x = TRUE, all.y = FALSE)
m[ order(m$order), ]

这里有几个流行的面向数据框的包可以用来代替上面的最后两行。 order 列未在这些解决方案中使用,可以从 DF 中省略以用于以下内容。

library(dplyr)
DF %>% left_join(mapDF)

library(data.table)
data.table(mapDF)[DF, on = "let"]

library(sqldf)
sqldf("select * from DF left join mapDF using (let)")

【讨论】:

  • 这是最好的答案,毫无疑问,尤其是第一个解决方案效果很好,而且它更加直观和直接,因为它不需要因子水平等。感谢您提供非常详细的答案和感谢您提供的大量解决方案!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多