我想过滤掉var3的所有值< 5同时保持var1的每个值至少出现一次。
> foo <- data.frame(var1=c(1, 1, 8, 8, 5, 5, 5), var2=c(1,2,3,2,4,6,8), var3=c(7,1,1,1,1,1,6))
> foo
var1 var2 var3
1 1 1 7
2 1 2 1
3 8 3 1
4 8 2 1
5 5 4 1
6 5 6 1
7 5 8 6
subset(foo, (foo$var3>=5))
会删除第2行到第6行,我会丢失var1 == 8。
这是我期望的结果:
var1 var2 var3
1 1 1 7
3 8 NA NA
7 5 8 6
这是我最接近的:
> foo$var3[ foo$var3 < 5 ] = NA
> foo$var2[ is.na(foo$var3) ] = NA
> foo
var1 var2 var3
1 1 1 7
2 1 NA NA
3 8 NA NA
4 8 NA NA
5 5 NA NA
6 5 NA NA
7 5 8 6
现在我只需要知道如何有条件地删除正确的行(2,3 或 4,5,6):如果var2&amp;删除行。 var3是NA,如果var1的值多于1次。
但是,确实有一种更为简单/优雅的方法可以解决这个小问题。
修改:将foo
更改为更符合我的用例
答案 0 :(得分:10)
最快的方法是使用merge:
> merge(foo[foo$var3>5,],unique(foo$var1),by.x=1,by.y=1,all.y=T)
var1 var2 var3
1 1 1 7
2 5 8 6
3 8 NA NA
unique(foo$var1)
给出var1中的唯一值。这些映射针对var3大于5的数据帧。你得到每个参数的第一列(all.x = 1,all.y = 1),你说y中的所有值都应该被表示(all.y = T)。另请参阅?merge
。
如果您想保留订单,请:
> merge(foo[foo$var3>5,],unique(foo$var1),by.x=1,by.y=1,
+ all.y=T)[order(unique(foo$var1)),]
var1 var2 var3
1 1 1 7
3 8 NA NA
2 5 8 6
merge对发生映射的变量进行排序。 order
给出了这种排序,因此您可以使用该顺序作为索引来反转它。另请参阅?order
。
答案 1 :(得分:3)
完成后:
foo$var3[ foo$var3 < 5 ] = NA
foo$var2[ is.na(foo$var3) ] = NA
您需要删除包含NA的行,这些行也是var1的重复值:
foo[!(!complete.cases(foo) & duplicated(foo$var1)), ]
将此行视为标识包含NA值和重复var1值的行,然后选择其他所有内容。
编辑:如果给定值var1的数据框中的第一行具有您要排除的值var3,则我的解决方案不起作用。您需要首先订购data.frame以确保完整的案例首先出现:
foo <- foo[order(foo$var2),] # ordering on var3 should be the same
foo[!(!complete.cases(foo) & duplicated(foo$var1)), ]
答案 2 :(得分:2)
rbind(r <- subset(foo, (foo$var3>=5)),
unique(transform(subset(foo, !var1%in%r$var1), var2=NA, var3=NA)))
一步步骤:
r <- subset(foo, (foo$var3>=5))
r2 <- subset(foo, !var1%in%r$var1) # extract var1 != r$var1
r3 <- transform(r2, var2=NA, var3=NA) # replace var2 and var3 with NA
r4 <- unique(r3) # remove duplicates
rbind(r, r4) # bind them
答案 3 :(得分:1)
以下是使用plyr
包函数ddply
和colwise
以及subset
函数的方法。首先定义辅助函数null2na
:
null2na <- function(x) if ( length(x) == 0 ) NA else x
接下来定义我们要应用于具有filter
特定值的每个子数据框的函数var1
:
filter <- function(df) cbind( data.frame( var1 = df[1,1]),
colwise(null2na) (subset(df, var3 >= 5)[,-1]))
现在ddply
foo
上的var1
> ddply(foo, .(var1), filter)
var1 var2 var3
1 1 1 7
2 5 8 6
3 8 NA NA
:
{{1}}
答案 4 :(得分:0)
试试这个:
foo <- data.frame(var1= c(1, 1, 2, 3, 3, 4, 4, 5),
var2=c(9, 5, 13, 9, 12, 11, 13, 9),
var3=c(6, 8, 3, 6, 4, 7, 2, 9))
f2=foo[which(foo$var3>5),]
missing = which(!(foo$var1 %in% f2$var1))
f3 = rbind(f2, list(foo$var1[missing], rep(NA, length(missing)),rep(NA,length(missing))))
f3[order(f3$var1),]
只有在关心订单时才需要最后一行(假设数据首先在var1上排序=。