对我的向量到列的代码进行优化

huangapple go评论63阅读模式
英文:

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(&quot;Population&quot; = c(&quot;4.88M&quot;, &quot;3.12M&quot;, &quot;819k&quot;,  &quot;4660&quot;,  &quot;46.7k&quot;, &quot;4.86M&quot;, &quot;856k&quot;))
int_list &lt;- numeric(nrow(df))
for (y in 1:nrow(df)) {
  i &lt;- df$Population[y]
  if (str_detect(i, &quot;k&quot;)){
    no_k &lt;- gsub(&quot;k&quot;, &quot;&quot;, i)
    x &lt;- as.numeric(no_k)
    fix_X &lt;- x * 1000
  } else if (str_detect(i, &quot;M&quot;)) {
    no_M &lt;- gsub(&quot;M&quot;, &quot;&quot;, i)
    x &lt;- as.numeric(no_M)
    fix_X &lt;- x * 1000000
  } else {
    fix_X &lt;- as.numeric(i)
  }
  int_list[y] = fix_X
}
df$pop_fix &lt;- 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(&quot;k&quot;, &quot;e3&quot;, sub(&quot;M&quot;, &quot;e6&quot;, 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 &lt;- list(k = &quot;e3&quot;, M = &quot;e6&quot;)
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(&quot;.&quot;, list(M=&quot;e6&quot;,k=&quot;e3&quot;), 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 &lt;- gsub(&quot;[^Mk]&quot;, &quot;&quot;, df$Population)
val &lt;- as.numeric(gsub(&quot;[Mk]&quot;,  &quot;&quot;, df$Population))
df$pop_fix2 &lt;- ifelse(sel == &quot;&quot;, val, val * c(&quot;M&quot;=1000000, &quot;k&quot;=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(&quot;pop&quot;, &quot;pop_scale&quot;)] &lt;- data.table::tstrsplit(df$Population, &quot;(?=(M|k))&quot;, perl = TRUE)
df$pop_scale              &lt;- replace(df$pop_scale, is.na(df$pop_scale), &quot;as_is&quot;)
df$pop                    &lt;- as.numeric(df$pop)
df$pop_fix                &lt;- 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

huangapple
  • 本文由 发表于 2023年5月22日 07:48:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76302357.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定