我正在尝试修复数据中的异常值,并将数据转换为R中下面组织的结构。
company_1(数据框中的一列)有12行数据,每6行数据指的是一个句点,因此有2个句点。
company_1
1 123
2 0
3 567
4 0
5 987
6 678
7 657
8 567
9 543
10 345
11 2341
12 5432
我正在寻找的是:对于我的数据框中的每一列,我想将0和大于其标准差的值修复为相应的时间段值(+或 - 6行) ),如果相应的时间段值也是异常值,则它会查找下一个(或前一个)对应的时间段值,直到检查完所有相应的时间段值。
我在下面尝试过代码,想法是将一个列数据填充到矩阵中,然后第一行将是原始列的第6行和第12行,第18行的值。
> sd.value <- as.numeric(apply(df,2, function(x) sd(x, na.rm = TRUE)))
> for(i in 1:dim(df)[2]){
> for(j in 1:dim(df)[1]){
> if(df[j,i] == 0 | df[j,i] >= sd.value[i]*3){
> df[j,i] <- matrix(data = df[,i], nrow = 6, ncol = 2)[j,][matrix(data = df[,i], nrow = 6, ncol = 2)[j,]!=0 & matrix(data
> = df[,i], nrow = 6, ncol = 2)[j,] <= sd.value[i]*3][1]
> } else{
> df[j,i] <- df[j,i]
> }
> }
> }
矩阵将是这样的:
[,1] [,2]
[1,] 123 657
[2,] 0 567
[3,] 567 543
[4,] 0 345
[5,] 987 2341
[6,] 678 5423
但是,这个for循环只能处理前6个值。这是因为,例如,对于原始列中的第8行,它应该检查该矩阵中的第2行值并确定是否需要修复它。但是,我不知道如何指示R检查&#39;矩阵的第二行,而i = 8,14 ......
感谢任何帮助。
答案 0 :(得分:0)
以下功能可能对您有所帮助。 fixCol用于根据条件固定向量中的值:0和大于其标准差的值被定义为异常值。异常值将被下一个非异常值对应的时间段值(+6行)替换。如果不存在这种非异常值,则异常值保持不变。
fixCol接受data.frame的向量或列作为输入,并返回固定向量。
注意:代码使用dplyr包和链接%&gt;%来修改data.frame。这比循环更有效,并且易于理解。
希望它有所帮助!
library(dplyr)
# fill NA values using the new non-NA value
# the NAs after the last non-NA values are unchanged
fillNaUseNextNonNa <- function(vecTest)
{
vecPre <- rep(vecTest[!is.na(vecTest)], diff(c(0,which(!is.na(vecTest)))))
vecNew <- c(vecPre, rep(NA, length(vecTest)-length(vecPre)))
return(vecNew)
}
# use the closet precedent non-na value to replace. if not found, use the closet following non-na value
fillNaBackward <- function(vecTest)
{
if(all(is.na(vecTest))) stop("All values are NA or invalid")
# (firstNonNaValue, vecTest)
vecTest <- c(vecTest[which(!is.na(vecTest))[1]], vecTest)
vecAfterTest <- rep(vecTest[!is.na(vecTest)], diff(c(which(!is.na(vecTest)), length(vecTest)+1)))
# vecNew <- c(vecPre, rep(NA, length(vecTest)-length(vecPre)))
return(vecAfterTest[-1])
}
# fix the values in a vector based on conditions in R
fixCol <- function(vecNum){
sdValueTri <- sd(vecNum, na.rm = TRUE)
# vecValid <- (vecNum == 0 | vecNum >= sdValueTri)
dfTmp <-data.frame(num = vecNum, valid = !(vecNum == 0 | vecNum >= sdValueTri))
# group
# then fix
dfTmp <- dfTmp %>%
group_by(group=row_number()%%6) %>%
mutate(numNew = ifelse(valid, num, NA)) %>%
mutate(numNew = fillNaBackward(numNew)) %>%
mutate(numNew = ifelse(is.na(numNew), num, numNew)) %>%
ungroup() %>%
select(numNew)
return(dfTmp$numNew)
}
# example
df <- data.frame(company_1 = c(123,0,567,0,987,678,657,567,543,345,2341,5432))
df <- df %>% mutate(company_1_fix = fixCol(company_1))
# df$company_1_fix
# 123 567 567 345 987 678 657 567 543 345 987 678