楼主: 梦孟小宝
8187 14

[问答] R 如何分组求差分 [推广有奖]

  • 4关注
  • 1粉丝

已卖:384份资源

硕士生

62%

还不是VIP/贵宾

-

威望
0
论坛币
10542 个
通用积分
14.4625
学术水平
10 点
热心指数
16 点
信用等级
8 点
经验
2574 点
帖子
78
精华
0
在线时间
216 小时
注册时间
2012-11-16
最后登录
2022-11-21

楼主
梦孟小宝 发表于 2017-2-11 14:51:35 |AI写论文
100论坛币
数据data有如下变量:
id为患者编号,disease为病种,time1为入院时间,time2为出院时间。现在要新建一列outcome,指代患者是否治疗有效。规则是:若患者t天内(后次住院的出院时间与前次住院的出院时间之间的间隔)因同样病种住院,则判断前次住院治疗无效。
尝试了很多方法,都没有成功,不知道论坛有没有高手能指点下。希望尽量避免循环,如果必须循环实现也可以。 sample_211.xlsx (31.97 KB)

最佳答案

zerofung 查看完整内容

我理解和表达可能有点错乱。是这样的: 需要分n=1 和 n > 1然后再合并,是肯定的。 n=1的全部赋予good,也是对的。 n>1的部分,应该改为time3 = lead(time1) - time2,这样可以使得good 和 bad 对应着前一次治疗。 另外rbind避免出错,需要确保两个data列数是对应的,你可以给前一个加个全是NA的time3列,也可以后一个去掉time3这一列。应该表达完整了吧,望采纳,祝成功。
关键词:disease outcome time Data ease 如何 新建

回帖推荐

cheetahfly 发表于14楼  查看完整内容

cheetahfly 发表于10楼  查看完整内容

沙发
zerofung 学生认证  发表于 2017-2-11 14:51:36
梦孟小宝 发表于 2017-2-12 08:31
arrange 那个问题是我自己弄错了,不好意思~
我理解和表达可能有点错乱。是这样的:
需要分n=1 和 n > 1然后再合并,是肯定的。
n=1的全部赋予good,也是对的。
n>1的部分,应该改为time3 = lead(time1) - time2,这样可以使得good 和 bad 对应着前一次治疗。
另外rbind避免出错,需要确保两个data列数是对应的,你可以给前一个加个全是NA的time3列,也可以后一个去掉time3这一列。应该表达完整了吧,望采纳,祝成功。
已有 1 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
admin_kefu + 20 + 2 + 2 + 2 热心帮助其他会员

总评分: 论坛币 + 20  学术水平 + 2  热心指数 + 2  信用等级 + 2   查看全部评分

藤椅
梦孟小宝 发表于 2017-2-11 15:09:08
如果用stata软件很好处理:
以id,disease分组,对每一行求上次同患者同病因住院的出院时间,计算这次入院和上次出院的时间间隔,若时间间隔大于t,则对outcome赋值1。 bysort id disease: gen last_time2=time2[_n-1]; gen interval=time1-last_time2; gen outcome=0; replace outcome=1 if interval>30
但是不知道R应该怎么写程序

板凳
zerofung 学生认证  发表于 2017-2-11 19:13:08
能不能提供一下作为例子的数据?

报纸
zerofung 学生认证  发表于 2017-2-11 19:56:43
初步想法是这样的,
library(tidyverse)
data %>% group_by(id,disease) %>% #是按患者和病种分组
  filter(n() > 1) %>%  #某患者同病种只入院一次的,就没有“有效无效”一说了对不对
  arrange(id,disease,time1) %>%  #按入院时间排序,后面的入院肯定比前一次出院时间靠后对不对
  mutate(time3 = time1 - lag(time2)) %>% #lag应该就是本问题核心了,用入院时间减去上一次出院时间,所得结果作为time3列
  mutate(outcome = ifelse(time3 < t, "bad", "good")) #根据time3与t的大小比较做outcome列,完成


当然啦你的日期需要是可以加减计算的格式而不是字符串,推荐lubridate包。

地板
梦孟小宝 发表于 2017-2-12 00:11:10
zerofung 发表于 2017-2-11 19:56
初步想法是这样的,
library(tidyverse)
data %>% group_by(id,disease) %>% #是按患者和病种分组
谢谢回复!!非常感谢你在我只言片语中能完全弄清楚我的问题!
样本数据(sample_211.xls)已经上传到本帖中,但是只是一小部分样本,有可能没有同患者因同病种多次住院的情况,但是对于您了解数据情况和编写程序应该够了。
还有几个问题想请教:
1. arrange(id,disease,time1) 时间数据可以arrange排序吗?我运行的时候总是报错“Error in UseMethod("arrange_") :   no applicable method for 'arrange_' applied to an object of class "function"”
2. filter之后是相当于新生成了一个数据集,还是在原始数据的基础上进行了更改呢?若患者同病种只入院一次,那暂且判断患者治疗有效,也就是对应的outcome的值是good。outcome的数据(包括有效和无效的病例)是要在后续分析中使用的,所以需要在原始数据data中进行更改,而不是生成一个只包含n>2的数据集。
3. 日期数据as.Date 之后不能直接加减运算吗?如果用lubridate包,能不能说具体点怎么用呢?是要跟mutate函数和lag函数整合使用吗?
我也是最近刚学习R,有很多不明白的地方,请多多指点,谢谢啦!终于看到可行的曙光了~谢谢~

7
梦孟小宝 发表于 2017-2-12 08:31:44
梦孟小宝 发表于 2017-2-12 00:11
谢谢回复!!非常感谢你在我只言片语中能完全弄清楚我的问题!
样本数据(sample_211.xls)已经上传到本帖 ...
arrange 那个问题是我自己弄错了,不好意思~

8
zerofung 学生认证  发表于 2017-2-12 10:55:08
梦孟小宝 发表于 2017-2-12 08:31
arrange 那个问题是我自己弄错了,不好意思~
跑了一下你的数据没有成功,因为你给的数据里没有患者因同病种二次入院的。
另外里面很多一整行完全重复的,你首先需要用filter(!duplicated(id,disease,time1,time2))来去掉重复的。
然后是lubridate包,很好学的。你的数据就加载包后data$time1 <- dmy(data$time1),time2同理,就好了,具体网上很多教程。lubridate包使R里的时间处理变得简单,不一定跟mutate整合使用的,怎么用都行。lag也是R自带的,怎么用都行,不依赖其他包。
filter的确是生成了新的数据集,但是你要清楚,同病种第一次住院,outcome不可能有good还是bad的(毕竟是对比出来的),所以肯定会有些记录的outcome是NA。所以如果按照你的意思,你可以把n=1的先提出来,都赋予good,其他的按照上面算,然后两个合并(rbind)就好啦。

9
梦孟小宝 发表于 2017-2-12 11:52:12
zerofung 发表于 2017-2-12 10:55
跑了一下你的数据没有成功,因为你给的数据里没有患者因同病种二次入院的。
另外里面很多一整行完全重复 ...
非常感谢!!!!我明天试试!希望成功!!

10
cheetahfly 在职认证  发表于 2017-2-12 19:54:18
  1. library(tidyverse)
  2. library(lubridate)

  3. # 需要专门针对本应用设计一个函数
  4. judge <- function(vec1, vec2, date, t) { #vec1和vec2对应time1和time2,date指数据统计截止的日期(等下有用了),t指阈值(单位是天)
  5.     stopifnot(is.Date(vec1) && is.Date(vec2)) # 确保两个向量是日期格式
  6.     n <- length(vec1)
  7.     out <- c(ifelse(vec1[-1] - vec2[-n] > t, "Success", "Failure"),
  8.              ifelse(date - vec2[n] > t, "Success", "Unkown"))
  9.     #最近的一次出院日期(包括只有一个记录的情况)应该和统计截止日对比,如果差距大于t说明治疗成功;如果差距小于t,应该是“不确定”。
  10.     out
  11. }

  12. data %>%
  13.     group_by(id, disease) %>%
  14.     arrange(time1) %>%
  15.     mutate(SoF = judge(time1, time2, ymd(20151130), 30))
  16. Source: local data frame [491 x 5]
  17. Groups: id, disease [484]

  18.                                  id disease      time1      time2     SoF
  19.                               <chr>   <chr>     <date>     <date>   <chr>
  20. 1  02051870a0a314e4bca5fa3a122d2be0    K635 2015-11-04 2015-11-08  Unkown
  21. 2  02350b503a0a1269a2f4e94088d60079    K635 2015-10-27 2015-11-01  Unkown
  22. 3  04245b4515128dc7292fe3d589502f80    K635 2015-05-18 2015-05-22 Success
  23. 4  045bcde962545ede2f103d7a127cc594    K635 2015-04-13 2015-04-16 Success
  24. 5  04876f0cb057d51d18ec09b1436f26c8    K635 2015-06-16 2015-06-19 Success
  25. 6  04d569d8a6a48795c49e030777bfc832    K635 2015-05-06 2015-05-13 Success
  26. 7  058d6006bc601aa15fed3f8cd7f06fdc    K635 2015-07-27 2015-07-30 Success
  27. 8  062ed5071ab25773f79c4c8aa1dbf517    K635 2015-12-09 2015-12-10  Unkown
  28. 9  072c54726572c1b63d407d3690da62ad    K635 2015-05-26 2015-06-02 Success
  29. 10 0771c5a2f35ea9fee01716a44546fb25    K635 2015-10-09 2015-10-15 Success
  30. # ... with 481 more rows
复制代码


已有 2 人评分论坛币 学术水平 热心指数 收起 理由
梦孟小宝 + 5 + 1 + 1 热心帮助其他会员
admin_kefu + 20 + 2 热心帮助其他会员

总评分: 论坛币 + 25  学术水平 + 1  热心指数 + 3   查看全部评分

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

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