在同一data.frame中分组/重新编码因子

时间:2010-10-06 18:15:35

标签: r

假设我有一个这样的数据框:

df <- data.frame(a=letters[1:26],1:26)

我想“重新”将a,b和c分解为“a”。

我该怎么做?

5 个答案:

答案 0 :(得分:14)

一个选项是包recode()中的car功能:

require(car)
df <- data.frame(a=letters[1:26],1:26)
df2 <- within(df, a <- recode(a, 'c("a","b","c")="a"'))
> head(df2)
  a X1.26
1 a     1
2 a     2
3 a     3
4 d     4
5 e     5
6 f     6

a并非如此简单,我们将多个级别重新编码为一个的示例。

set.seed(123)
df3 <- data.frame(a = sample(letters[1:5], 100, replace = TRUE),
                  b = 1:100)
with(df3, head(a))
with(df3, table(a))

最后一行给出:

> with(df3, head(a))
[1] b d c e e a
Levels: a b c d e
> with(df3, table(a))
a
 a  b  c  d  e 
19 20 21 22 18

现在,我们可以使用a

将等级eZ合并到等级recode()
df4 <- within(df3, a <- recode(a, 'c("a","e")="Z"'))
with(df4, head(a))
with(df4, table(a))

给出:

> with(df4, head(a))
[1] b d c Z Z Z
Levels: b c d Z
> with(df4, table(a))
a
 b  c  d  Z 
20 21 22 37

在不拼写要合并的级别的情况下执行此操作:

## Select the levels you want (here 'a' and 'e')
lev.want <- with(df3, levels(a)[c(1,5)])
## now paste together
lev.want <- paste(lev.want, collapse = "','")
## then bolt on the extra bit
codes <- paste("c('", lev.want, "')='Z'", sep = "")
## then use within recode()
df5 <- within(df3, a <- recode(a, codes))
with(df5, table(a))

这与我们上面的df4相同:

> with(df5, table(a))
a
 b  c  d  Z 
20 21 22 37 

答案 1 :(得分:13)

有没有人尝试过这种简单的方法?它不需要特殊的包装,只需了解R如何处理因素。

假设您要重命名因子中的级别,获取其索引

data <- data.frame(a=letters[1:26],1:26)
lalpha <- levels(data$a)

在这个例子中,我们想象我们想知道级别'e'和'w'

的索引
lalpha <- levels(data$a)
ind <- c(which(lalpha == 'e'), which(lalpha == 'w'))

现在我们可以使用此索引来替换因子'a'

的级别
levels(data$a)[ind] <- 'X'

如果您现在查看数据系数因子a,那么会有一个X,其中有ew

我留给你试试结果。

答案 2 :(得分:3)

您可以执行以下操作:

df$a[df$a %in% c("a","b","c")] <- "a"

更新:更复杂的因素。

Data <- data.frame(a=sample(c("Less than $50,000","$50,000-$99,999",
  "$100,000-$249,999", "$250,000-$500,000"),20,TRUE),n=1:20)
rows <- Data$a %in% c("$50,000-$99,999", "$100,000-$249,999")
Data$a[rows] <- "$250,000-$500,000"

答案 3 :(得分:2)

有两种方法。 如果你不想放弃未使用的等级,即“b”和“c”,Joshua的解决方案可能是最好的。

如果你想放弃未使用的等级,那么

df$a<-factor(ifelse(df$a%in%c("a","b","c"),"a",as.character(df$a)))

levels(df$a)<-ifelse(levels(df$a)%in%c("a","b","c"),"a",levels(df$a))

答案 4 :(得分:0)

这是所选答案的简化版本:

我发现解决这个问题的最简单方法就是通过查看因子水平来覆盖因子水平,然后将数字写下来覆盖。

df <- data.frame(a=letters[1:26],1:26)
levels(df)

> [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" 
 "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z"

levels(df$a)[c(1,2)] <- "c"
summary(df$a)

> c d e f g h i j k l m n o p q r s t u v w x y z 
  3 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1