id <- c(1:8,1:8)
age1 <- c(7.5,6.7,8.6,9.5,8.7,6.3,9,5)
age2 <- age1 + round(runif(1,1,3),1)
age <- c(age1, age2)
tanner <- sample(1:2, 16,replace=T)
df <- data.frame(id,age,tanner)
id age tanner
1 1 7.5 2
2 2 6.7 1
3 3 8.6 2
4 4 9.5 2
5 5 8.7 1
6 6 6.3 1
7 7 9.0 1
8 8 5.0 1
9 1 10.0 1
10 2 9.2 1
11 3 11.1 1
12 4 12.0 2
13 5 11.2 2
14 6 8.8 2
15 7 11.5 1
16 8 7.5 1
以上是示例数据框。我想将其转换为以下格式。
id age at tanner=1 age at tanner=2
1 10 7.5
2 6.7 NA
3 11.1 8.6
4 NA 9.5
...
如果在两个年龄段,制革商记录是相同的,我希望它保持年龄较小。
例如,
id age tanner
2 6.7 1
2 9.2 1
在这种情况下,将在新数据集中为id = 2保留6.7。
答案 0 :(得分:3)
reshape
然后df
(使用您的reshape(
aggregate(age ~ ., data=df, FUN=min),
idvar="id", timevar="tanner", direction="wide"
)
# id age.1 age.2
#1 1 10.0 7.5
#2 2 6.7 NA
#3 3 11.1 8.6
#4 5 8.7 11.2
#5 6 6.3 8.8
#6 7 9.0 NA
#7 8 5.0 NA
#10 4 NA 9.5
的复制和粘贴版本,而不是您的代码,但不匹配):
{{1}}
答案 1 :(得分:1)
我们可以使用dcast
从'long'转换为'wide',并将fun.aggregate
用作min
。在这里,我将'data.frame'转换为'data.table'(setDT(df)
),因为来自dcast
的{{1}}会很快。
data.table
如果我们想将'Inf'更改为'NA'
library(data.table)
res <- dcast(setDT(df), id~paste('age',tanner,sep='.'), value.var='age', min)
res
# id age.1 age.2
#1: 1 10.0 7.5
#2: 2 6.7 Inf
#3: 3 11.1 8.6
#4: 4 Inf 9.5
#5: 5 8.7 11.2
#6: 6 6.3 8.8
#7: 7 9.0 Inf
#8: 8 5.0 Inf
答案 2 :(得分:0)
这里有一点dplyr
和tidyr
。 arrange
按年龄显示最低年龄,然后使用filter
获取重复的ID / tanner,然后使用tidyr::spread
df<-
data.frame(
id = c(1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8)
,age = c(7.5, 6.7, 8.6, 9.5, 8.7, 6.3, 9.0, 5.0,10.0, 9.2,11.1,12.0,11.2, 8.8,11.5, 7.5)
,tanner = c(2,1,2,2,1,1,1,1,1,1,1,2,2,2,1,1)
)
library(dplyr)
library(tidyr)
wide <-
df %>%
arrange(age) %>%
filter(!duplicated(paste(id, tanner))) %>%
spread(tanner, age)
colnames(wide) = c('id', 'tanner1', 'tanner2')
wide
# id 1 2
# 1 10.0 7.5
# 2 6.7 NA
# 3 11.1 8.6
# 4 NA 9.5
# 5 8.7 11.2
# 6 6.3 8.8
# 7 9.0 NA
# 8 5.0 NA