首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >R dplyr折叠行并指定一个表示整数范围的标签。

R dplyr折叠行并指定一个表示整数范围的标签。
EN

Stack Overflow用户
提问于 2019-07-10 23:45:30
回答 3查看 342关注 0票数 1

下面是一个转换的简化表示,我需要将它应用于一个大型复杂表。在这里,输入表是一个有两个数字列的查找。rawSS有着多对一的关系.raw的许多值可以具有相同的SS值,但反之亦然。

代码语言:javascript
复制
library(tidyverse)
input <- tribble(
  ~raw, ~SS,
  0, 75,
  1,    78,
  2,    80,
  3,    83,
  4,    83,
  5,    83,
  6,    90,
  7,    93,
  8,    95,
  9,    98
)

所需的输出表如下。

代码语言:javascript
复制
output <- tribble(
  ~SS, ~raw,
  100, '-',
  99, '-',
  98, '9',
  97, '-',
  96, '-',
  95, '8',
  94, '-',
  93, '7',
  92, '-',
  91, '-',
  90, '6',
  89, '-',
  88, '-',
  87, '-',
  86, '-',
  85, '-',
  84, '-',
  83, '3-5',
  82, '-',
  81, '-',
  80, '2',
  79, '-',
  78, '1',
  77, '-',
  76, '-',
  75, '0',
  74, '-',
  73, '-',
  72, '-',
  71, '-',
  70, '-'
)

要创建此输出,需要通过以下几种方式转换输入:

  1. 列重排
  2. SS列填充了所有缺失的整数(70:100),并按降序排序。
  3. raw列强制使用字符,有三种类型的值来保留原始SS:的多对一关系。
    • 一个破折号“-”表示SS的值,没有对应的raw值(例如,SS = 70)
    • SS值的单个值(例如,'2'),其对应值为raw (例如,SS = 80)
    • 具有多个对应值的SS值的范围(例如,'3-5') (例如,SS = 83)

以下是我在这方面取得的成就:

代码语言:javascript
复制
interim <- input %>% select(
  SS, raw
    ) %>% 
  mutate_at(
    vars(
      raw
      ), ~ as.character(.x)
    ) %>% 
  complete(
      SS = 70:100
      ) %>% 
  arrange(
      desc(
        SS
        )
      ) %>% 
  mutate_at(
    vars(
      raw
    ), ~ case_when(
      is.na(.x) ~ '-',
      TRUE ~ .x
    )
  )

如果您运行上述代码,您将看到唯一剩下的转换是将三行SS = 83行折叠为一行,其中对应的raw值为'3-5'。这意味着以某种方式认识到3和5是范围的下界和上界,因为解将需要处理不确定长度的连续整数的范围。

提前感谢您的帮助!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-07-11 00:09:11

一个选项是complete,然后执行group_by paste

代码语言:javascript
复制
library(tidyverse)
out1 <- input  %>% 
          complete(SS = 70:100, fill = list(raw = '-')) %>%      
          group_by(SS) %>% 
          summarise(raw = if(n() > 1) str_c(range(raw), collapse='-') else raw) %>% 
          arrange(desc(SS)) 
out1
# A tibble: 31 x 2
#      SS raw  
#   <dbl> <chr>
# 1   100 -    
# 2    99 -    
# 3    98 9    
# 4    97 -    
# 5    96 -    
# 6    95 8    
# 7    94 -    
# 8    93 7    
# 9    92 -    
#10    91 -    
# … with 21 more rows

带OP输出的-checking

代码语言:javascript
复制
identical(out1, output)
#[1] TRUE

或在filter之前使用group_by后的paste步骤。

代码语言:javascript
复制
input %>% 
  complete(SS = 70:100, fill = list(raw = '-')) %>% 
  group_by(SS) %>% 
  filter(n() == 1| n() > 1 & row_number()  %in% c(1, n())) %>% 
  summarise(raw = str_c(raw, collapse = '-')) %>%
  arrange(desc(SS))
票数 1
EN

Stack Overflow用户

发布于 2019-07-10 23:54:50

有一种方法-

代码语言:javascript
复制
tibble(SS = 100:70) %>% 
  left_join(input, by = "SS") %>% 
  replace_na(list(raw = "-")) %>% 
  group_by(SS) %>% 
  summarize(raw = paste0(unique(range(raw)), collapse = "-")) %>% 
  arrange(desc(SS))

# A tibble: 31 x 2
      SS raw  
   <dbl> <chr>
 1   100 -    
 2    99 -    
 3    98 9    
 4    97 -    
 5    96 -    
 6    95 8    
 7    94 -    
 8    93 7    
 9    92 -    
10    91 -    
11    90 6    
12    89 -    
13    88 -    
14    87 -    
15    86 -    
16    85 -    
17    84 -    
18    83 3-5  
19    82 -    
20    81 -    
21    80 2    
22    79 -    
23    78 1    
24    77 -    
25    76 -    
26    75 0    
27    74 -    
28    73 -    
29    72 -    
30    71 -    
31    70 -   
票数 1
EN

Stack Overflow用户

发布于 2019-07-11 03:25:19

data.table解决方案:

代码语言:javascript
复制
input_dt[, .(raw = ifelse(.N == 1, as.character(raw), paste(min(raw), max(raw), sep = '-'))), by = SS
         ][data.table(SS = 70:100), on = 'SS'
           ][is.na(raw), raw := '-'
             ][order(-SS)]

base

代码语言:javascript
复制
out_2 <- merge(data.frame(SS = 70:100)
               , aggregate(raw ~ SS
                           , data = input
                           , FUN = function(x) ifelse(length(x) == 1, as.character(x), paste(min(x), max(x), sep = '-')))
               , by = 'SS'
               , all.x = TRUE
)

out_2$raw <- ifelse(is.na(out_2$raw), '-', out_2$raw)
out_2[order(-out_2$SS), ]

数据:

代码语言:javascript
复制
library(tibble)
input <- tribble(
  ~raw, ~SS,
  0, 75,
  1,    78,
  2,    80,
  3,    83,
  4,    83,
  5,    83,
  6,    90,
  7,    93,
  8,    95,
  9,    98
)

library(data.table)

input_dt <- as.data.table(input)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56979935

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档