从一组观察中创建群组样式的数据框架

时间:2015-12-23 21:08:57

标签: r reshape

我是R的新手并且有一个简单的问题,因为我还在学习R数据操作/管理的风格。

我有一段时间观察基本临床特征(血压,胆固醇等)的数据集。每个观察都有患者ID和日期,但作为单独的行项目输入。像这样:

Patient ID    Date  Blood Pressure
         1 21/1/14             120
         1 19/3/14             134
         1  3/5/14             127

我想转换数据,使得对于给定的变量(例如血压),我有一个数据框,每个患者一行,并且按时间顺序在整个时间内观察到的所有血压值。像这样:

Patient ID BP1 BP2 BP3 
         1 120 134 127

我想这样做,因为我希望能够编写代码来选择前三个观察到的血压的平均值,例如。

非常感谢任何建议或阅读建议。

4 个答案:

答案 0 :(得分:3)

您可以通过多种方法重新整形数据来实现所需的格式,包括使用Base R中的IIS_IUSRS函数或reshape()包中的dcast(),但它可能更容易能够直接使用一种聚合形式获得答案。以下是使用reshape2包中的ddply()的一种方法:

plyr

当然,如果你真的只想做你所问的事,你可以做以下事情:

library(plyr)

df <- read.table(text="id  date  bp
1 21/1/14             120
1 19/3/14             134
1  3/5/14             127",header=TRUE)

df1 <- ddply(df, .(id), summarize, mean.bp = mean(bp[1:3]))

df1
#   id mean.bp
# 1  1     127

答案 1 :(得分:3)

 # example dataframe
id <- c(rep(1:4,25))
date <- c(rep("21/01/14",30),rep("21/01/14",30),rep("22/01/14",30),rep("23/01/14",10))
bp <- c(rnorm(100,100))
df <- data.frame(id,date,bp)

# reorder the dataframe
library(dplyr)
df2 <- group_by(df,id) # group by id
df2 <- arrange(df2, date) # order each group by date
df3 <- mutate(df2,   # add a colum with ascending number per for each group
              c = 1:length(date))

# use dcast
library(reshape2)
dcast(df3[,c(1,4,3)],id~c)

答案 2 :(得分:3)

使用包(对meltdcast功能的改进实施),您可以按以下方式执行此操作:

newdf <- dcast(setDT(df)[, idx := 1:.N, by = id], id ~ paste0("bp",idx), value.var = "bp")

或使用新的rowid功能:

newdf <- dcast(setDT(df), id ~ rowid(prefix="bp",id), value.var = "bp")

两个选项都给出了相同的结果:

> newdf
   id bp1 bp2 bp3
1:  1 120 134 129
2:  2 110 124 119

但正如@SamDickson所说,当您想要计算(例如)前两次血压测量的平均值时,您还可以使用以下内容向现有数据框df添加新变量:

# using base R
df$first2mn <- ave(df$bp, df$id, FUN = function(x) mean(x[1:2])) 
# using data.table
setDT(df)[, first2mn := mean(bp[1:2]), id] 

两者都给出了:

> df
   id    date  bp first2mn
1:  1 21/1/14 120      127
2:  1 19/3/14 134      127
3:  1  3/5/14 129      127
4:  2 21/1/14 110      117
5:  2 19/3/14 124      117
6:  2  3/5/14 119      117

或者只计算平均值:

# using base R
aggregate(bp ~ id, df, function(x) mean(x[1:2])) 
# using data.table
setDT(df)[, .(bp = mean(bp[1:2])), id] 

两者都给出了:

  id  bp
1  1 127
2  2 117

使用过的数据:

df <- read.table(text="id  date  bp
1 21/1/14             120
1 19/3/14             134
1  3/5/14             129
2 21/1/14             110
2 19/3/14             124
2  3/5/14             119", header=TRUE)

答案 3 :(得分:0)

其他答案提供了许多计算组间平均值的方法。 related post提供了许多计算组级别最大值的方法。您需要在这些答案中将TypeError: Cannot read property 'Symbol(Symbol.iterator)' of undefined at Array.any (C:\dev\nodejs\testproject\dist\routes\userRoutes.js:29:39) at C:\dev\nodejs\testproject\dist\routes\userRoutes.js:87:56 at Query.<anonymous> (C:\dev\nodejs\testproject\node_modules\mongoose\lib\model.js:3748:16) at C:\dev\nodejs\testproject\node_modules\kareem\index.js:277:21 at C:\dev\nodejs\testproject\node_modules\kareem\index.js:131:16 at _combinedTickCallback (internal/process/next_tick.js:67:7) at process._tickCallback (internal/process/next_tick.js:98:9) 替换为max

这是使用基本R函数mean重新整形宽度的另一种方法。

使用@jaap提供的data.frame,添加一个变量用于按ID计算观察结果:

reshape

现在,执行重塑,删除不需要的日期变量:

df$times <- ave(df$bp, df$id, FUN=seq_along)