我有以下data.frame df
:
df = data.frame(col1 = c('a','a','a','a','a','b','b','c','d'),
col2 = c('a','a','a','b','b','b','b','a','a'),
height1 = c(NA,32,NA,NA,NA,NA,NA,25,NA),
height2 = c(31,31.5,NA,NA,11,12,13,NA,NA),
col3 = 1:9)
# col1 col2 height1 height2 col3
#1 a a NA 31.0 1
#2 a a 32 31.5 2
#3 a a NA NA 3
#4 a b NA NA 4
#5 a b NA 11.0 5
#6 b b NA 12.0 6
#7 b b NA 13.0 7
#8 c a 25 NA 8
#9 d a NA NA 9
我希望col1, col2
中的每个值都能构建一个包含以下值的列height
:
NA
和height1
中只有height2
,请返回NA
。height1
中有值,请取此值。 (对于一对col1, col2
,non NA
列中最多只有一个height1
值NA
中只有height1
,non NA
中有height2
个值,请取height2
中的第一个值。我还需要在col3
列中保留相应的值。
新的data.frame
new.df
将如下所示:
# col1 col2 height col3
#1 a a 32 2
#2 a b 11 5
#3 b b 12 6
#4 c a 25 8
#5 d a NA 9
我更喜欢data.frame
方法,非常简洁,但我意识到我无法找到它!
答案 0 :(得分:4)
也许不是您正在寻找的优雅解决方案,但这里有一个base R
选项:
do.call("rbind",
lapply(split(df,paste0(df$col1,df$col2)),
function(tab) {
colnames(tab)[3:4] <- "height"
out <- if(any(!is.na(tab[, 3]))) {
tab[which(!is.na(tab[,3])),-4]
} else {
if (any(!is.na(tab[,4]))) {
tab[which(!is.na(tab[,4]))[1],c(1:2,4:5)]
} else {
tab[1,-4]
}
}
return(out)
}
)
)
# col1 col2 height col3
# aa a a 32 2
# ab a b 11 5
# bb b b 12 6
# ca c a 25 8
# da d a NA 9
答案 1 :(得分:2)
使用dplyr:
df %>%
mutate(
order = ifelse(!is.na(height1), 1, ifelse(!is.na(height2), 2, 3)),
height = ifelse(!is.na(height1), height1, ifelse(!is.na(height2), height2, NA))
) %>%
arrange( col1, col2, order, height) %>%
distinct(col1, col2) %>%
select( col1, col2, height, col3)
答案 2 :(得分:1)
我使用data.table
(而我想在那里使用data.frame选项异常)并且我发现我的解决方案不优雅:
func = function(df)
{
if(all(is.na(subset(df, select=c(height1,height2)))))
return(df[1,])
if(any(!is.na(df$height1)))
return(df[!is.na(df$height1),])
df[!is.na(df$height2),][1,]
}
setDT(df)
new.df=df[,func(.SD),by=list(col1,col2)]
new.df = data.frame(new.df)
new.df$height = ifelse(is.na(new.df$height1), new.df$height2, new.df$height1)
#> new.df
# col1 col2 height1 height2 col3 height
#1 a a 32 31.5 2 32
#2 a b NA 11.0 5 11
#3 b b NA 12.0 6 12
#4 c a 25 NA 8 25
#5 d a NA NA 9 NA