3

给定一个data.frame,我想测试所有列是否属于同一个“类”。如果他们是,我想保留 data.frame 原样。如果不是,我想保留与第一个变量类匹配的所有列,并删除任何不属于该类的列。唯一的例外是,就我的目的而言,整数和数字是相等的。

例如:

dat <- data.frame(numeric,numeric,integer,factor) 

将会:

data.frame(numeric,numeric,integer) 

此外

dat <- data.frame(character,character,integer)

将会:

data.frame(character,character) 

最后:

dat <- data.frame(numeric,numeric,numeric,factor)

将会:

data.frame(numeric,numeric,numeric)
4

3 回答 3

4

我会这样做:

dat <- data.frame(
  a=as.integer(1:26), b=as.integer(26:1), c=as.numeric(1:26), d=as.factor(1:26)
)

创建两个辅助函数:

is.numint <- function(x)is.numeric(x) || is.integer(x)
is.charfact <- function(x)is.character(x) || is.factor(x)

仅返回数字列:

head(dat[, sapply(dat, is.numint)])
    a  b  c
1   1 26  1
2   2 25  2
3   3 24  3
4   4 23  4
5   5 22  5

仅返回因子列:

head(dat[, sapply(dat, is.charfact), drop=FALSE])
  d
1 1
2 2
3 3
4 4
5 5
6 6

结合这种方法,并重写你的函数:

dropext <- function(x){
  is.numint <- function(x)is.numeric(x) || is.integer(x)
  is.charfact <- function(x)is.character(x) || is.factor(x)
  cl <- rep(NA, length(x))
  cl[sapply(x, is.numint)] <- "num"
  cl[sapply(x, is.charfact)] <- "char"
  x[, cl == unique(cl)[1], drop=FALSE]
}

dropext(dat)
    a  b  c
1   1 26  1
2   2 25  2
3   3 24  3
4   4 23  4
5   5 22  5
于 2012-11-02T20:43:03.893 回答
3

怎么样:

if(length(unique(cl <- sapply(dat, class))) > 1 && 
   any(!sapply(dat, is.numeric))) {
    dat <- dat[ , which(cl == cl[1]), drop = FALSE]
}

这假设在以下示例中:

dat2 <- data.frame(A = factor(sample(LETTERS, 26, replace = TRUE)),
                   B = factor(sample(LETTERS, 26, replace = TRUE)),
                   C = sample(LETTERS, 26, replace = TRUE),
                   dat, stringsAsFactors = FALSE)


> sapply(dat2, class)
               A                B                C 
        "factor"         "factor"      "character" 
as.integer.1.26. as.integer.26.1. as.numeric.1.26. 
       "integer"        "integer"        "numeric" 

需要因子变量,即您想要区分字符变量和因子变量 - 这就是您的代码似乎要做的事情。

对于这个例子,我使用

if(length(unique(cl <- sapply(dat2, class))) > 1 &&
   any(!sapply(dat2, is.numeric))) {
    dat2 <- dat2[ ,which(cl == cl[1]), drop = FALSE]
}

这导致

> head(dat2)
  A B
1 D G
2 P D
3 C T
4 X F
5 N R
6 A E
> sapply(dat2, class)
       A        B 
"factor" "factor"

dat,上面的if()语句不会改变dat

>     if(length(unique(cl <- sapply(dat, class))) > 1 && 
+         any(!sapply(dat, is.numeric))) {
+         dat <- dat[ , which(cl == cl[1]), drop = FALSE]
+     }
> head(dat)
  as.integer.1.26. as.integer.26.1. as.numeric.1.26.
1                1               26                1
2                2               25                2
3                3               24                3
4                4               23                4
5                5               22                5
6                6               21                6
于 2012-11-02T21:04:31.463 回答
1

感谢您的评论和您的回答,最后我只需要一个不区分整数和数字的 class() 函数。这可以通过一个简单的包装器来完成。

class.wrap <- function(x) {
test <- class(x) 
if(test == "integer") test <- "numeric"
return(test)
} 
于 2012-11-02T22:18:37.057 回答