替换数据集中的所有负值

Replacing all negative values from a dataset

我有一个 dataframe 混合数据,范围从具有数值的变量(或列)到具有因子的变量(或列)。

我想在 R 中使用以下代码将所有负值替换为 NA,如果该变量的 99% 以上的观察值是 NA,则随后删除整个变量。

第一部分要保证遇到字符串没有问题。 是否可以简单地从以下开始:

mydata$v1[mydata$v1<0] <- NA 

但不是特定于 v1 且仅当观察不是字符串时?

跟进: 这是我对@stas g 提供的解释的理解。然而,似乎没有从 df 中删除任何变量。

#mixed data
df <- data.frame(WVS_Longitudinal_1981_2014_R_v2015_04_18)
dat <- df[,sapply(df, function(x) {class(x)== "numeric" | class(x) == 
"integer"})]

foo <- function(dat, p){ 
  ind <- colSums(is.na(dat))/nrow(dat)
  dat[dat < 0] <- NA
  dat[, ind < p]
}

#process numeric part of the data separately
ii <- sapply(df, class) == "numeric" | sapply(df, class) == "integer"
dat.num <- foo(as.matrix(df[, ii]), 0.99)
#then stick the two parts back together again
WVS <- data.frame(df[, !ii], dat.num)

如果没有最小的可重现示例,就不可能确切地知道如何为您提供帮助,但假设您有以下示例数据:

#matrix of random normal observations, 20 samples, 5 variables
dat <- matrix(rnorm(100), nrow = 20)
#if entry is negative, replace with 'NA'
dat[dat < 0] <- NA

#threshold for dropping a variable
p <- 0.99
#check how many NAs in each column (proportionally)
ind <- colSums(is.na(dat))/nrow(dat)
#only keep columns where threshold is not exceded
dat <- dat[, ind < p]

如果你有非数字变量并且你正在处理 data.frame 你可以这样做(假设你不关心列的顺序):

#generate mixed data
dat <- matrix(rnorm(100), nrow = 20) #20 * 50 numeric numbers
df <- data.frame(letters[1 : 20], dat) #combined with one character column 


foo <- function(dat, p){ 
  ind <- colSums(is.na(dat))/nrow(dat)
  dat[dat < 0] <- NA
  dat[, ind < p]
}

#process numeric part of the data separately
ii <- sapply(df, class) == "numeric" #ind of numeric columns
dat.num <- foo(as.matrix(df[, ii]), 0.99) #feed numeric part of data to foo
#then stick the two partw back together again
data.frame(df[, !ii], dat.num)

这种方法: @YOLO 的建议最终解决了问题:

cleanFun <- function(df){

    # set negative values as NA
    df[df < 0] <- NA

    # faster, vectorized solution
    # select numeric columns
    num_cols <- names(df)[sapply(df, is.numeric)]

    # get name of columns with 99% or more NA values
    col_to_remove <- names(df)[colMeans(is.na(df[num_cols]))>=0.99]

    # drop those columns
    return (df[setdiff(colnames(df),col_to_remove)])
}

your_df <- cleanFun(your_df)