英文:
Code optimization for my vector to columns
问题
df = data.frame("Population" = c("4.88M", "3.12M", "819k", "4660", "46.7k", "4.86M", "856k"))
int_list <- numeric(nrow(df))
for (y in 1:nrow(df)) {
i <- df$Population[y]
if (str_detect(i, "k")){
no_k <- gsub("k", "", i)
x <- as.numeric(no_k)
fix_X <- x * 1000
} else if (str_detect(i, "M")) {
no_M <- gsub("M", "", i)
x <- as.numeric(no_M)
fix_X <- x * 1000000
} else {
fix_X <- as.numeric(i)
}
int_list[y] = fix_X
}
df$pop_fix <- int_list
英文:
Would there be a better way to better optimize this code in R
df = data.frame("Population" = c("4.88M", "3.12M", "819k", "4660", "46.7k", "4.86M", "856k"))
int_list <- numeric(nrow(df))
for (y in 1:nrow(df)) {
i <- df$Population[y]
if (str_detect(i, "k")){
no_k <- gsub("k", "", i)
x <- as.numeric(no_k)
fix_X <- x * 1000
} else if (str_detect(i, "M")) {
no_M <- gsub("M", "", i)
x <- as.numeric(no_M)
fix_X <- x * 1000000
} else {
fix_X <- as.numeric(i)
}
int_list[y] = fix_X
}
df$pop_fix <- int_list
EDIT: added an example DF
I got the result I needed just wondering if I could do better
I have tried ifelse statements but they always lead to errors and I've also tried to just put it in the column but then it overwrites the past values to the last one
答案1
得分: 2
1) 这里是一个一行的代码。没有使用任何包。
transform(df, pop_fix = as.numeric(sub("k", "e3", sub("M", "e6", Population))))
## Population pop_fix
## 1 4.88M 4880000
## 2 3.12M 3120000
## 3 819k 819000
## 4 4660 4660
## 5 46.7k 46700
## 6 4.86M 4860000
## 7 856k 856000
2) 或者使用 Reduce
L <- list(k = "e3", M = "e6")
transform(df, pop_fix = as.numeric(Reduce(\(x, nm) sub(nm, L[[nm]], x),
init = Population, names(L))))
3) 这也可以,从概念上讲,它同时执行了两个替换:
library(gsubfn)
transform(df, pop_fix = as.numeric(gsubfn(".", list(M="e6",k="e3"), Population)))
英文:
1) Here is a one-liner. No packages are used.
transform(df, pop_fix = as.numeric(sub("k", "e3", sub("M", "e6", Population))))
## Population pop_fix
## 1 4.88M 4880000
## 2 3.12M 3120000
## 3 819k 819000
## 4 4660 4660
## 5 46.7k 46700
## 6 4.86M 4860000
## 7 856k 856000
2) or using Reduce
L <- list(k = "e3", M = "e6")
transform(df, pop_fix = as.numeric(Reduce(\(x, nm) sub(nm, L[[nm]], x),
init = Population, names(L))))
3) This also works and conceptually does both substitutions at once:
library(gsubfn)
transform(df, pop_fix = as.numeric(gsubfn(".", list(M="e6",k="e3"), Population)))
答案2
得分: 1
这里是一个简化的尝试。只保留k/M
后缀,然后去掉k/M
,使用一些后缀的索引来确定乘数:
sel <- gsub("[^Mk]", "", df$Population)
val <- as.numeric(gsub("[Mk]", "", df$Population))
df$pop_fix2 <- ifelse(sel == "", val, val * c("M"=1000000, "k"=1000)[sel])
给出了所请求的结果:
# Population pop_fix pop_fix2
#1 4.88M 4880000 4880000
#2 3.12M 3120000 3120000
#3 819k 819000 819000
#4 4660 4660 4660
#5 46.7k 46700 46700
#6 4.86M 4860000 4860000
#7 856k 856000 856000
英文:
Here's an attempt at simplifying. Strip out everything but the k/M
suffixes, then strip out the k/M
, and use some indexing of the suffixes to determine the multiplier:
sel <- gsub("[^Mk]", "", df$Population)
val <- as.numeric(gsub("[Mk]", "", df$Population))
df$pop_fix2 <- ifelse(sel == "", val, val * c("M"=1000000, "k"=1000)[sel])
Gives the requested result:
# Population pop_fix pop_fix2
#1 4.88M 4880000 4880000
#2 3.12M 3120000 3120000
#3 819k 819000 819000
#4 4660 4660 4660
#5 46.7k 46700 46700
#6 4.86M 4860000 4860000
#7 856k 856000 856000
答案3
得分: 1
我们可以使用tidyverse。首先,从指数器中“分离”数字。然后将符号指数转换为正确的10进制数,最后通过简单的乘法调整人口。
library(dplyr)
library(tidyr)
df %>%
separate_wider_regex(col = Population,
patterns = c(population = "[0-9.]+",
magnitude = "[A-Za-z]"),
too_few = "align_start"
) %>%
type_convert() %>%
mutate(magnitude = case_match(magnitude,
"M" ~ 6,
"k" ~ 3,
.default = 1
)
) %>%
mutate(population = population * (10^ magnitude),
.keep = "none")
A tibble: 7 × 1
population
1 4880000
2 3120000
3 819000
4 46600
5 46700
6 4860000
7 856000
<details>
<summary>英文:</summary>
We can use the tidyverse. First `separate` the numeric from the exponentiator. Then convert the symbolic exponentiator to a proper base 10 number, and finally adjust the population by a simple multiplication.
library(dplyr)
library(tidyr)
df |>
separate_wider_regex(col = Population,
patterns = c(population = "[0-9.]+",
magnitude = "[A-Za-z]"),
too_few = "align_start"
) |> type_convert() |>
mutate(magnitude = case_match(magnitude,
"M" ~ 6,
"k" ~ 3,
.default = 1
)
) |>
mutate(population = population * (10^ magnitude),
.keep = "none")
A tibble: 7 × 1
population
<dbl>
1 4880000
2 3120000
3 819000
4 46600
5 46700
6 4860000
7 856000
答案4
得分: 1
I've translated the code portion for you:
df[c("pop", "pop_scale")] <- data.table::tstrsplit(df$Population, "(?=(M|k))", perl = TRUE)
df$pop_scale <- replace(df$pop_scale, is.na(df$pop_scale), "as_is")
df$pop <- as.numeric(df$pop)
df$pop_fix <- df$pop * c(M=1e6, k=1e3, as_is=1)[df$pop_scale]
The rest of the content remains the same.
英文:
df[c("pop", "pop_scale")] <- data.table::tstrsplit(df$Population, "(?=(M|k))", perl = TRUE)
df$pop_scale <- replace(df$pop_scale, is.na(df$pop_scale), "as_is")
df$pop <- as.numeric(df$pop)
df$pop_fix <- df$pop * c(M=1e6, k=1e3, as_is=1)[df$pop_scale]
# Population pop pop_scale pop_fix
# 1 4.88M 4.88 M 4880000
# 2 3.12M 3.12 M 3120000
# 3 819k 819.00 k 819000
# 4 4660 4660.00 as_is 4660
# 5 46.7k 46.70 k 46700
# 6 4.86M 4.86 M 4860000
# 7 856k 856.00 k 856000
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论