楼主: rosenbloog
4158 17

[问答] 如何补齐有规律的文本(或数字)序列 [推广有奖]

11
king64 发表于 2016-2-12 11:21:53
rosenbloog 发表于 2016-2-9 23:07
数据里暂时没有可以group_by的变量
没有group ID? 你不会做一个吗??

使用jianbeilu的方法做一个,比如:rep(1:3,10)

然后与你的数据合并在一起,缺失的地方用NA补充上!

12
蓝色 发表于 2016-2-12 11:27:13
没有分组变量,只是看到 c("max", "unit", "rate"),也是很难办的

可能都是同一组
也可能是不同组
也可能是前两个是一组,第三个是一组
也可能是前一个是一组,后两个是一组
如下所示
x            groupID1    groupID2   groupID3   groupID4
max           1               1              1              1
unit           1               1              2              2
rate           1               2              2             3

这些情况都可能发生,如果没有分组变量
假如不知道是哪种分组的情况,就麻烦了
如果真实的情况是groupid4的这样
但是分组产生的是groupid1的情况或其他情况,可想而知,后面进一步分析可能就是错的了


所以,还是想办法从原始数据里面找到分组的groupid为好
而且也应该有才对


13
cheetahfly 在职认证  发表于 2016-2-13 09:41:25
蓝色 发表于 2016-2-12 11:27
没有分组变量,只是看到 c("max", "unit", "rate"),也是很难办的

可能都是同一组
按照楼主的说法,就如题目所说的“有规律的文本(或数字)序列”,这个规律,我从楼主的话中理解为:第一,同一组中,一定是按照max,unit,rate的顺序排列(下表中对应1、2、3),反复循环,不规则缺失;第二,每一组中,中间的unit不会缺失。

根据这两个规律,可以推断,缺失组一般有以下三种,1)缺max,2)缺rate,3)既缺max,也缺rate,它们的组合可以归结为:
  
  

max



rate



既缺max,也缺rate


  

max

  

Unit 2

  

Rate 3

  

Unit 2

  

Rate 3



Max 1

  

Unit 2

  

Max 2

  

Unit 3



Unit 2

  

Unit 2

  

Rate 3


  

rate

  

Unit 2

  

Rate 3

  

Max 1

  

Unit 2



Max 1

  

Unit 2

  

Max 1

  

Unit 2



Unit 2

  

Max 1

  

Unit 2


  

既缺max,也缺rate

  

Unit 2

  

Rate 3

  

Unit 2



Max 1

  

Unit 2

  

Unit 2



Unit 2

  

Unit 2


各种情况都可以用一个简单判定法则来分组:就是数字没有增长。(这也是czrdiao同学用一阶差分和是否<=0来判定分组的理由)

最后说明一下,这里的group.id仅仅是为了标明每个max、unit、rate循环在数据框中的相对位置而设定的,清洗完数据后完全可以删除,不用赋予其实际意义(事实上也没有实际意义)。

14
cheetahfly 在职认证  发表于 2016-2-13 09:56:29
czrdiao 发表于 2016-2-12 08:48
如果真的是cheetahfly说的,我这个方法好像比较简单
x = c("max", "unit", "rate", "max", "unit", "rate" ...
czrdiao同学创造性地用一阶差分和向量化rep来解决该问题,给了我很大的启发,多谢!

我一直有种感觉,这个问题可以有一个非常简单直接的解决方法的。受czrdiao同学思路的启发,我另想了一个简化思路:既然group.id是用来标明相对位置和寻找缺失行的相对坐标,因此,没有必要一定从max开始循环。我完全可以跳开第一行,然后从第二行的unit开始循环,这样,在同样可以解决问题的条件下,语句只需要简化成一行即可:

group.id <- cumsum(data[,1] == "unit")

有了标明每组(无论是否完整)max、unit、rate循环的相对位置的group.id后,要解决楼主所提出来的补齐数据就比较容易了,一个思路是用大神Hadley Wickham提出来的Split-Apply-Combine策略,用plyr::ddply()来解决;另一个思路按向量化的方式,根据setdiff()函数,找出缺失max行和rate行的相对“坐标”,然后创建——合并——排序,具体怎么做就不啰嗦了。

15
suimong 发表于 2016-2-14 19:21:33
题主的问题应该适用tidyr::complete函数

16
cheetahfly 在职认证  发表于 2016-2-14 23:15:59
suimong 发表于 2016-2-14 19:21
题主的问题应该适用tidyr::complete函数
多谢提醒。不知是不是我查阅得不对,该运用函数的前提仍然需要有group.id这一列?

有了tidyr::complete之后,确实第二步工作就很简单了,只需要:
library(tidyr)
library(dplyr)
df %>% complete(group.id, nesting(a))  #假设max,unit,rate所在列的列名为“a”

注意,这里的group.id需要正确形式的,比如10楼、9楼的方法算出的,不能用14楼的简化算法。

17
suimong 发表于 2016-2-15 20:08:02
cheetahfly 发表于 2016-2-14 23:15
多谢提醒。不知是不是我查阅得不对,该运用函数的前提仍然需要有group.id这一列?

有了tidyr::c ...
确实,要向量化解决这个问题group id列是少不了的。综合使用@czrdiao的差分方法和你提到的cumsum函数,group_id列的生成其实并不复杂:
library(tidyr)
library(dplyr)

# 重新构造测试数据,包括所有可能的缺失情况
x <- c("max", "unit", "rate",
       "max", "unit", "rate",
       "unit", "rate",
       "max", "unit",
       "unit",
       "max", "unit")
lvls <- c("max", "unit", "rate")
int_code <- unclass(factor(x, levels=lvls))

# 用差分标记出分组的起始位置,并在差分的头部添加第一组的标记0(或者其他<=0的值)
group_mark <- ifelse(c(0, diff(int_code)) <= 0, 1, 0)
# 由分组标记计算出group_id
group_id <- cumsum(group_mark)

# 利用tidyr::complete函数计算出每组中缺失的值
data <- data_frame(group_id, int_code, x)
data %>% complete(group_id, int_code)

18
cheetahfly 在职认证  发表于 2016-2-15 23:04:40
suimong 发表于 2016-2-15 20:08
确实,要向量化解决这个问题group id列是少不了的。综合使用@czrdiao的差分方法和你提到的cumsum函数,gr ...
perfectly done

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2025-12-29 03:45