在NAs上传播价值

时间:2013-04-04 21:38:10

标签: r split dataframe

我有一个data.frame,我希望将其分成一个列表。

我有:

data.frame(value=c(1:4,NA,11:12,NA,21:23,NA),
           key=as.factor(c(NA,NA,NA,NA,"a",NA,NA,"b",NA,NA,NA,"c")))
   value  key
1      1 <NA>
2      2 <NA>
3      3 <NA>
4      4 <NA>
5     NA    a
6     11 <NA>
7     12 <NA>
8     NA    b
9     21 <NA>
10    22 <NA>
11    23 <NA>
12    NA    c

我想:

list(a=data.frame(value=1:4), 
     b=data.frame(value=11:12),
     c=data.frame(value=21:23))
$a
  value
1     1
2     2
3     3
4     4

$b
  value
1    11
2    12

$c
  value
1    21
2    22
3    23

如果我可以将split列转换为

,我应该可以使用key来获取我想要的内容
[1] a a a a a b b b c c c c
Levels: a b c
但是,唉,我不知道该怎么做。

3 个答案:

答案 0 :(得分:3)

这将为您提供平面向量,如果您愿意,可以split

library(zoo)
na.locf(f$key, fromLast = TRUE)

[1] a a a a a b b b c c c c
Levels: a b c

答案 1 :(得分:2)

这是我的解决方案:

> f <- data.frame(value=c(1:4,NA,11:12,NA,21:23,NA),
                  key=as.factor(c(NA,NA,NA,NA,"a",NA,NA,"b",NA,NA,NA,"c")))
> keys <- f$key
> good <- !is.na(keys)
> f$key <- NULL
> l <- split(f,head(cumsum(c(0,good)),-1))
> names(l) <- keys[good]
> lapply(l, function(df) head(df,-1))
$a
  value
1     1
2     2
3     3
4     4

$b
  value
6    11
7    12

$c
   value
9     21
10    22
11    23

有更好的方法吗?

具体来说,我不喜欢的是

  1. head + cumsum + c组合难看
  2. lapply + head组合很丑陋

答案 2 :(得分:1)

这也很脏,但是如果你不介意丑陋的循环就行了

> dat <- data.frame(value=c(1:4,NA,11:12,NA,21:23,NA),key=as.factor(c(NA,NA,NA,NA,"a",NA,NA,"b",NA,NA,NA,"c")))
> 
> labels <- which(!is.na(dat$key))
> j <- 1
> for(i in labels){
+   dat$key[j:i] <- dat$key[i]
+   j = i + 1
+ }
> 
> split(dat$value[!is.na(dat$value)],as.factor(dat$key[-labels]))
$a
[1] 1 2 3 4

$b
[1] 11 12

$c
[1] 21 22 23