我有团队排名数据,其中一列具有“ Xth of Y”形式的条目。我需要将它们转换为0到1比例的数值,其中1st是1,last是0,其余部分以线性比例出现。我已经考虑过strsplit(),但是不知道该如何处理某些“第一”,某些“第二”等。举个例子,我的数据看起来像
x = as.factor(c('2nd of 6', '5th of 5', '4th of 5', '3rd of 5', '5th of 5', '4th of 7'))
注意:“ 6之2”应转换为0.8,而不是0.6666667
答案 0 :(得分:2)
我们可以从字符串中提取数字,将其分割,然后创建一个介于0和1之间的序列,其长度由第二个数字决定,并从该序列中将第一个数字作为子集。
sapply(strsplit(sub("^(\\d+)(?:st|nd|rd|th) of (\\d+).*", "\\1-\\2", x), "-"),
function(x) 1 - seq(0, 1, length.out = as.integer(x[2]))[as.integer(x[1])])
#[1] 0.80 0.00 0.25 0.50 0.00 0.50
答案 1 :(得分:1)
OP之前没有提到预期的输出。因此,我们将根据另一篇文章的评论更改输出。
df1 <- read.csv(text= gsub("\\D+", ",", x), header = FALSE)
1 - unlist(Map(function(x, y) seq(0, 1, length.out = y)[x], df1$V1, df1$V2))
#[1] 0.80 0.00 0.25 0.50 0.00 0.50
我们可以使用base R
单行执行
1- Reduce(`/`, read.csv(text= gsub("\\D+", ",", x), header = FALSE))
#[1] 0.6666667 0.0000000 0.2000000 0.4000000 0.0000000 0.4285714
或与strsplit
m1 <- sapply(strsplit(as.character(x), "\\D+"), as.numeric)
1 - m1[1,]/m1[2,]
或与fread
library(data.table)
fread(text=gsub("\\D+", ",", x))[, 1- Reduce(`/`, .SD)]
#[1] 0.6666667 0.0000000 0.2000000 0.4000000 0.0000000 0.4285714
或使用tidyverse
library(tidyverse)
x %>%
str_replace("\\D+", ",") %>%
tibble(col1 = .) %>%
separate(col1, into = c('col1', 'col2'), convert = TRUE) %>%
reduce(`/`) %>%
-1 *-1
#[1] 0.6666667 0.0000000 0.2000000 0.4000000 0.0000000 0.4285714