我有一个大数据库,但是为了这个练习,我们可以使用这个:
c-1 c-2 c-3 c-4 c-5 c-6
1-14 14-29 NA NA NA NA
60-90 CF CF CF CF CF
C 1-14 14-29 CF NA NA
60-90 CF CF CF NA NA
我想要的是将所有在前一列中获得CF的列更改为HF,这样看起来像这样:
c-1 c-2 c-3 c-4 c-5 c-6
1-14 14-29 NA NA NA NA
60-90 CF HF HF HF HF
C 1-14 14-29 CF NA NA
60-90 CF HF HF NA NA
我试图通过这样的应用来做到这一点,但它没有正常工作
function_a <- function (x) {ifelse(df[,i]=="CF" & df[,i-1]=="CF", "HF", df[,i])}
new_df<- as.data.frame(lapply(length(df):1, function_a))
请记住,如果前一列不是CF,我想保留原始值,有没有简单的方法可以做到这一点?在R基地?
答案 0 :(得分:4)
我喜欢这个问题,因为直接将它看作是各种各样的滚动应用,但不是zoo::rollapply
意义上的(虽然它也可以在那里管理)。我在谈论使用Reduce(..., accumulate=TRUE)
。
您的数据:
dat <- data.frame(
c1 = c('1-14','60-90','C','60-90'),
c2 = c('14-29','CF','1-14','CF'),
c3 = c(NA,'CF','14-29','CF'),
c4 = c(NA,'CF','CF','CF'),
c5 = c(NA,'CF',NA,NA),
c6 = c(NA,'CF',NA,NA),
stringsAsFactors = FALSE
)
我正在添加逻辑以检查上一列中的"HF"
,否则您将获得交替"CF"
/ "HF"
。我推断,无论以前的列如何,NA
都应始终为NA
,因为这就是您的示例的外观。 (这个假设很容易被删除。)
func <- function(a, b) ifelse(! is.na(a) & ! is.na(b) & a %in% c("CF","HF"), "HF", b)
默认情况下,Reduce
仅返回最后一列的结果。使用accumulate=TRUE
,它返回每个调用的结果(加上第一列),我们将使用它来重新填充相同大小的帧。
df[] <- Reduce(func, df, right=FALSE, accumulate=TRUE)
df
# c1 c2 c3 c4 c5 c6
# 1 1-14 14-29 <NA> <NA> <NA> <NA>
# 2 60-90 CF HF HF HF HF
# 3 C 1-14 14-29 CF <NA> <NA>
# 4 60-90 CF HF HF <NA> <NA>
答案 1 :(得分:3)
另一个建议的解决方案是转置矩阵,将矩阵滞后1行,然后检查滞后矩阵中的CF和转置矩阵中的CF,最后转置回来得到所需的输出:
tdat <- t(dat)
lagged <- rbind(matrix(NA_character_, ncol=nrow(dat)), tdat[-nrow(tdat),])
tdat[lagged=="CF" & tdat=="CF"] <- "HF"
res <- t(tdat)
res
数据:
dat <- read.table(text="c-1 c-2 c-3 c-4 c-5 c-6
1-14 14-29 NA NA NA NA
60-90 CF CF CF CF CF
C 1-14 14-29 CF NA NA
60-90 CF CF CF NA NA", header=TRUE, check.names=FALSE)
答案 2 :(得分:3)
使用与原始数据大小相同的矩阵,查找第一次出现后连续出现的"CF"
个单元格:
sel <- dat == "CF" & (!is.na(dat))
dat[col(dat) > max.col(sel, "first") & sel] <- "HF"
dat
# c-1 c-2 c-3 c-4 c-5 c-6
#1 1-14 14-29 <NA> <NA> <NA> <NA>
#2 60-90 CF HF HF HF HF
#3 C 1-14 14-29 CF <NA> <NA>
#4 60-90 CF HF HF <NA> <NA>
使用@ r2evans'dat
对象。