You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用cut()函数为数据集添加区间类时返回NA值的问题排查

问题分析:cut()函数返回NA的原因及解决办法

问题重现

你希望基于以下数据集,为每行的Position字段添加对应LimAm到LimAv的区间类:

df <- structure(list(Position = c(1925.12260901036, 2463.70794121719, 
1282.23738714798), ID = c(11, 12, 24), LimAm = c(39943.8043856595, 
40482.3897178663, 39300.9191637971), LimAv = c(40443.8043856595, 
40982.3897178663, 39800.9191637971)), row.names = c(NA, -3L), class = c("tbl_df", 
"tbl", "data.frame"))

但执行以下代码后,class列全为NA:

df %>% mutate(class=cut(Position,c(LimAm, LimAv),include.lowest = FALSE))

输出结果:

# A tibble: 3 × 5
  Position    ID  LimAm  LimAv class
     <dbl> <dbl>  <dbl>  <dbl> <fct>
1    1925.    11 39944. 40444. NA   
2    2464.    12 40482. 40982. NA   
3    1282.    24 39301. 39801. NA

原因解析

1. 数值本身不匹配

所有Position的取值(1925、2464、1282)都远小于对应行的LimAm(39944、40482、39301),自然不在(LimAm, LimAv]这个区间内,返回NA是符合逻辑的结果。

2. cut()函数的用法误解

cut()的第二个参数breaks要求是全局统一的分割点向量,而非逐行对应的区间。当你传入c(LimAm, LimAv)时,它会把所有行的LimAm和LimAv合并成一个全局分割序列(比如示例中是c(39943.8,40482.39,39300.92,40443.8,40982.39,39800.92)),然后将每个Position放到这个全局分割的区间中,而非逐行匹配自身的LimAm和LimAv。
之前代码能正常运行是巧合——当时的Position刚好落在全局分割后的某个区间里,新增数据后全局分割区间变化,或者Position不再匹配,就出现了NA。

正确解决办法

要实现逐行判断Position是否在对应行的(LimAm, LimAv]区间,需要用逐行处理的方式,比如结合rowwise()或者purrr包的map2():

方法1:用rowwise()逐行处理

library(dplyr)

df %>%
  rowwise() %>%
  # 先判断是否在区间内,再生成区间标签或NA
  mutate(class = ifelse(Position > LimAm & Position <= LimAv,
                        paste0("(", round(LimAm, 1), ";", round(LimAv, 1), "]"),
                        NA_character_)) %>%
  ungroup()

如果想保留cut()生成的因子型结果,也可以在rowwise()内调用cut():

df %>%
  rowwise() %>%
  mutate(class = cut(Position, breaks = c(LimAm, LimAv), include.lowest = FALSE)) %>%
  ungroup()

方法2:用purrr::map2()逐行生成结果

library(dplyr)
library(purrr)

df %>%
  mutate(class = map2_chr(LimAm, LimAv, ~{
    ifelse(Position > .x & Position <= .y,
           paste0("(", round(.x, 1), ";", round(.y, 1), "]"),
           NA_character_)
  }))

补充说明

如果之前的数据集能正常运行,大概率是当时的Position数值落在了全局分割后的某个区间,或者你误将逐行区间的逻辑用在了全局分割上。正确的逐行区间匹配必须明确处理每行的独立区间,而不是依赖cut()的全局分割特性。

内容的提问来源于stack exchange,提问作者C. Guff

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:58:27