是否有 R 函数或 SQL 解决方案用于将所有相同的数字重复分组并将它们分配给所有行?
Posted
技术标签:
【中文标题】是否有 R 函数或 SQL 解决方案用于将所有相同的数字重复分组并将它们分配给所有行?【英文标题】:Is there an R function or SQL solution for grouping the all the same numbers repeatedly in a row and assign them to all rows?? 【发布时间】:2019-07-12 09:36:22 【问题描述】:我想将序列中的连续数字组合成一对。最终目标是计算每组的对数。
我尝试通过在 Redshift 中结合使用 row_number、lag 和 lead 来解决这个问题。
** 我不关心递减区间,但我只想在递增部分建群。
我的桌子
id number
ㅡㅡㅡㅡ
a | 0
a | 0
a | 1
a | 2
a | 3
a | 2
a | 1
a | 2
a | 1
预期
id number group
ㅡㅡㅡㅡㅡㅡㅡㅡㅡ
a | 0 | 0
a | 0 | 0
a | 1 | 3
a | 2 | 3
a | 3 | 3
a | 2 | 0
a | 1 | 2
a | 2 | 2
a | 1 | 0
决赛桌
group cnt
---------
2 | 2
3 | 3
提前致谢!
【问题讨论】:
我不明白预期的输出。组总是重要的吗?同样,对于组 2,为什么 1 得到一个分组?对于第 3 组,从 0 到 1 不会更改组列。那么为什么从 2 变为 1 会将组更改为“2”? @Cole 嗨,科尔,我想要的不是担心减少数量,而是只考虑增加的数量。此外,目标是根据增加部分中连续增加的次数对相同的数字进行分组。 SQL 解决方案需要第三个变量来指定行顺序。为什么四个连续的行 a0,a1,a2,a3 在一个值为 4 的组中(这会违反“仅在增加部分构建组”吗?或者相反,为什么 a1,a2 是一个组 = 2(不t 这违反了“仅在增加的部分中构建组”),而不是仅在组中的 a2 = 1 【参考方案1】:我的解决方案(有意将所有步骤留在预期的数据框中):
library(dplyr)
df<-tibble(id = "a", number = c(0,0,1,2,3,1,2,1))
expected <- df %>%
mutate(l = lag(number),
l = if_else(is.na(l), 0, l),
splits = l < number & l > 0, #remove & l > 0 if starting from 0 is allowed, change to l + 1 == number if step must be 1
g = cumsum(!splits)) %>%
group_by(g) %>%
mutate(group = n()) %>%
ungroup()
final <- expected %>%
filter(group != 1) %>%
group_by(group) %>%
summarise(cnt = n())
无论如何,group 和 cnt 的值在决赛桌中总是相同的,所以你可以使用 unique()。所以我不确定这是否是你所期望的
【讨论】:
这是我想要的解决方案。非常感谢您的帮助。【参考方案2】:你可以用一个 for 循环的方式来解决这个问题,它可以识别 min 的序列。 2 值,并为组变量分配序列中出现的最后一个数字的值。结果可以是提供组变量的原始数据集或聚合
X <- data.frame(number = c(0L,0L,1L,2L,3L,2L,1L,2L,1L))
aggrIt <- function(DF = X, raw = T)
g <- 1L
result <- rep(0L, nrow(DF))
for(i in seq_len(nrow(DF)))
if(i == nrow(DF)) break
if(i == 1L)
if(DF$number[i] != 0L && DF$number[i+1L] == DF$number[i] + 1L) result[i] <- g
if(DF$number[i] != 0L && DF$number[i+1L] != DF$number[i] + 1L) result[i] <- 0L
else
if(DF$number[i] != 0L && DF$number[i+1L] == DF$number[i] + 1L)
result[i] <- g
else
if(DF$number[i-1L] == DF$number[i] - 1L)
result[i] <- g
g <- g + 1L
transl <- tapply(DF$number[result != 0L], result[result != 0L], function(i) rep(max(i), length(i)), simplify = F)
DF$group <- 0L
DF$group[result %in% names(transl)] <- unlist(transl)
if(raw) return(DF)
return(setNames(aggregate(number~group, DF, length, subset = group != 0L), c("group", "cnt")))
aggrIt(X, raw= F)
#group cnt
#1 2 2
#2 3 3
aggrIt(X, raw = T)
#number group
#1 0 0
#2 0 0
#3 1 3
#4 2 3
#5 3 3
#6 2 0
#7 1 2
#8 2 2
#9 1 0
您可以将该功能应用于 id 组。
【讨论】:
感谢您的回答。这也是一个很好的解决方案。但是,我需要慢慢看才能理解整个逻辑。再次感谢您!以上是关于是否有 R 函数或 SQL 解决方案用于将所有相同的数字重复分组并将它们分配给所有行?的主要内容,如果未能解决你的问题,请参考以下文章
是否有任何包或方法可以将 data.table R 代码转换/发送为 sql 查询以发送到数据库?
是否有列出 SQL Server 中所有内置函数的系统表或系统视图?
是否有用于对数据帧的每一列执行基本操作的 R 函数? [复制]
R语言ggplot2可视化多因子分组条形图使用position_dodge2函数配置所有的条形宽度相同不管分组是否只有一个因子