将数据与'cut()合并后,创建标签的'chr'列`

将数据与'cut()合并后,创建标签的'chr'列`,r,tidyverse,R,Tidyverse,我已经使用cut()为我的一列数据创建了存储箱。使用以下mtcars可复制示例: library(tidyverse) df <- mtcars df$mpg_binned <- cut(x = df$mpg, breaks = 4) df <- df %>% select(mpg, mpg_binned, everything()) head(df) #> mpg mpg_binned cyl disp hp drat

我已经使用
cut()
为我的一列数据创建了存储箱。使用以下
mtcars
可复制示例:

library(tidyverse)
df <- mtcars

df$mpg_binned <- cut(x = df$mpg, breaks = 4)
df <- df %>% select(mpg, mpg_binned, everything())
head(df)

#>                    mpg  mpg_binned cyl disp  hp drat    wt  qsec vs am
#> Mazda RX4         21.0 (16.3,22.1]   6  160 110 3.90 2.620 16.46  0  1
#> Mazda RX4 Wag     21.0 (16.3,22.1]   6  160 110 3.90 2.875 17.02  0  1
#> Datsun 710        22.8   (22.1,28]   4  108  93 3.85 2.320 18.61  1  1
#> Hornet 4 Drive    21.4 (16.3,22.1]   6  258 110 3.08 3.215 19.44  1  0
#> Hornet Sportabout 18.7 (16.3,22.1]   8  360 175 3.15 3.440 17.02  0  0
#> Valiant           18.1 (16.3,22.1]   6  225 105 2.76 3.460 20.22  1  0

如果只有两个存储箱,我会使用
ifelse()
——对于多个存储箱,我是否需要执行嵌套的
ifelse()
?有更简单的吗

由于某种原因,我无法让下面的行工作,对于一个箱子的情况。我想给所有的垃圾箱贴上标签

Tidyverse解决方案会很棒,但我对所有解决方案都持开放态度

df$bin_label <- 
  ifelse(df2$mpg_binned=="(16.3,22.1]", yes = "16.3 < mpg <= 22.1", no = df2$mpg_binned)

df$bin_label由于我们事先不知道数据将被分割的确切的
断点是什么,一种选择是使用正则表达式提取数字。所以对于
mpg
列,我们可以

sub("\\((\\d+\\.?\\d?),(\\d+\\.?\\d?).*", "\\1 < mpg <= \\2", df$mpg_binned)
#[1] "16.3 < mpg <= 22.1" "16.3 < mpg <= 22.1" "22.1 < mpg <= 28"  
#    "16.3 < mpg <= 22.1" "16.3 < mpg <= 22.1" ......

由于我们事先不知道数据将被分割的确切的
断点是什么,一种选择是使用正则表达式来提取数字。所以对于
mpg
列,我们可以

sub("\\((\\d+\\.?\\d?),(\\d+\\.?\\d?).*", "\\1 < mpg <= \\2", df$mpg_binned)
#[1] "16.3 < mpg <= 22.1" "16.3 < mpg <= 22.1" "22.1 < mpg <= 28"  
#    "16.3 < mpg <= 22.1" "16.3 < mpg <= 22.1" ......

这里有一个带有
str\u replace
的选项,我们将数字部分捕获为一个组,并替换为该组的反向引用(
\\1
\\2
),其中穿插着我们要添加的字符串

library(tidyverse)
df %>% 
   rownames_to_column('rn') %>%
   mutate(bin_label  = str_replace(mpg_binned,
               "\\(([0-9.]+),([0-9.]+)\\]", "\\1 < mpg <= \\2")) %>%
   column_to_rownames('rn')

#                    mpg  mpg_binned cyl  disp  hp drat    wt  qsec vs am gear carb          bin_label
#Mazda RX4           21.0 (16.3,22.1]   6 160.0 110 3.90 2.620 16.46  0  1    4    4 16.3 < mpg <= 22.1
#Mazda RX4 Wag       21.0 (16.3,22.1]   6 160.0 110 3.90 2.875 17.02  0  1    4    4 16.3 < mpg <= 22.1
#Datsun 710          22.8   (22.1,28]   4 108.0  93 3.85 2.320 18.61  1  1    4    1   22.1 < mpg <= 28
#Hornet 4 Drive      21.4 (16.3,22.1]   6 258.0 110 3.08 3.215 19.44  1  0    3    1 16.3 < mpg <= 22.1
#Hornet Sportabout   18.7 (16.3,22.1]   8 360.0 175 3.15 3.440 17.02  0  0    3    2 16.3 < mpg <= 22.1
#Valiant             18.1 (16.3,22.1]   6 225.0 105 2.76 3.460 20.22  1  0    3    1 16.3 < mpg <= 22.1

这里有一个带有
str\u replace
的选项,我们将数字部分捕获为一个组,并替换为该组的反向引用(
\\1
\\2
),其中穿插着我们要添加的字符串

library(tidyverse)
df %>% 
   rownames_to_column('rn') %>%
   mutate(bin_label  = str_replace(mpg_binned,
               "\\(([0-9.]+),([0-9.]+)\\]", "\\1 < mpg <= \\2")) %>%
   column_to_rownames('rn')

#                    mpg  mpg_binned cyl  disp  hp drat    wt  qsec vs am gear carb          bin_label
#Mazda RX4           21.0 (16.3,22.1]   6 160.0 110 3.90 2.620 16.46  0  1    4    4 16.3 < mpg <= 22.1
#Mazda RX4 Wag       21.0 (16.3,22.1]   6 160.0 110 3.90 2.875 17.02  0  1    4    4 16.3 < mpg <= 22.1
#Datsun 710          22.8   (22.1,28]   4 108.0  93 3.85 2.320 18.61  1  1    4    1   22.1 < mpg <= 28
#Hornet 4 Drive      21.4 (16.3,22.1]   6 258.0 110 3.08 3.215 19.44  1  0    3    1 16.3 < mpg <= 22.1
#Hornet Sportabout   18.7 (16.3,22.1]   8 360.0 175 3.15 3.440 17.02  0  0    3    2 16.3 < mpg <= 22.1
#Valiant             18.1 (16.3,22.1]   6 225.0 105 2.76 3.460 20.22  1  0    3    1 16.3 < mpg <= 22.1

cut
还具有
labels
参数,您可以在其中指定正确的标签如果您想在使用
cut
后创建标签,因此无法使用
cut
的“labels”参数,请在使用
函数时尝试tidyverse的
case\u。这类似于
ifelse
,但可以更清晰地处理多个备选方案。
cut
还具有
labels
参数,如果要在使用
cut
后创建标签,则可以指定正确的标签,因此不能使用
cut
的“labels”参数,尝试tidyverse的
case\u when
功能。这类似于ifelse
,但更清晰地处理多个备选方案。我意识到,我上面提供的可复制示例实际上简化了我真实数据的一个关键方面。如果我想打印第二个捕获
\\2
减去一,我如何将其细分到标签列中?我尝试了使用
as.character(as.numeric(\\2)-1)作为
paste0
,但没有成功。再次感谢你。@JeremyK。如果你需要用它做一些数学运算,它不会直接工作,因为这些是字符,我们需要分别提取它们。我已经更新了答案。你的技能令人难以置信!非常感谢。我意识到我上面提供的可复制示例实际上简化了我真实数据的一个关键方面。如果我想打印第二个捕获
\\2
减去一,我如何将其细分到标签列中?我尝试了使用
as.character(as.numeric(\\2)-1)作为
paste0
,但没有成功。再次感谢你。@JeremyK。如果你需要用它做一些数学运算,它不会直接工作,因为这些是字符,我们需要分别提取它们。我已经更新了答案。你的技能令人难以置信!非常感谢。
df %>%
    rownames_to_column('rn') %>%
    mutate(bin_label = map_chr(str_extract_all(mpg_binned, "[0-9.]+"),
              ~ str_c(first(.x), "< mpg <= ", last(.x)))) %>%
   column_to_rownames('rn')