2014-08-28 46 views
4

我想要每个数据框的子集排除第一列是NA或“”的行。我尝试将数据帧放入列表df,然后在每个数据帧上使用lapply。该代码的作品,只是我不知道如何覆盖与子集的每个数据帧。lapply在dataframes列表子集和覆盖dfs

df1 <- data.frame(v1=c(1, 2, 3, NA, NA, NA), v2=rep(1, 6)) 
df2 <- data.frame(v11=c(2, 3, 4, 5, NA, ""), v22=rep(1, 6)) 
df3 <- data.frame(v111=c(3, 4, 5, 6, 7, NA), v222=rep(1, 6)) 

df <- list(df1=df1, df2=df2, df3=df3) 
df 

$df1 
# v1 v2 
# 1 1 1 
# 2 2 1 
# 3 3 1 
# 4 NA 1 
# 5 NA 1 
# 6 NA 1 
# 
# $df2 
# v11 v22 
# 1 2 1 
# 2 3 1 
# 3 4 1 
# 4 5 1 
# 5 <NA> 1 
# 6  1 
# 
# $df3 
# v111 v222 
# 1 3 1 
# 2 4 1 
# 3 5 1 
# 4 6 1 
# 5 7 1 
# 6 NA 1 

lapply(names(df), function(x) df[[x]][!(is.na(df[[x]][,1]) | df[[x]][,1]==""), ]) 

# [[1]] 
# v1 v2 
# 1 1 1 
# 2 2 1 
# 3 3 1 
# 
# [[2]] 
# v11 v22 
# 1 2 1 
# 2 3 1 
# 3 4 1 
# 4 5 1 
# 
# [[3]] 
# v111 v222 
# 1 3 1 
# 2 4 1 
# 3 5 1 
# 4 6 1 
# 5 7 1 

最后,我想df3,例如,如下:

df3 
# v111 v222 
#1 3 1 
#2 4 1 
#3 5 1 
#4 6 1 
#5 7 1 
+1

好问题。我从中学到了一些东西。 – 2014-08-28 19:49:28

回答

6

您可以简化lapply以下形式(为了保持名称的数据帧太)

df <- lapply(df, function(x) x[!(is.na(x[1]) | x[1] == ""), ]) 

然后用list2env在为了让你的数据帧重新回到全球环境中

list2env(df, .GlobalEnv) 

然后你就可以通过只

df1 
## v1 v2 
## 1 1 1 
## 2 2 1 
## 3 3 1 

+0

是的!多么有趣的小函数'list2env'。其他人可能会推荐@ nrussell的答案来修改列表中的dfs,但我问了如何覆盖原始的df对象,并且这样做很好。 – 2014-08-28 19:42:48

+0

我也不知道那个。 (+1)。男人,我今天学习很多! – 2014-08-28 19:46:34

0

如何complete.cases

df2[df2==""] <- NA 
lapply(df, FUN = function(x) x[complete.cases(x),]) 

$df1 
    v1 v2 
1 1 1 
2 2 1 
3 3 1 

$df2 
    v11 v22 
1 2 1 
2 3 1 
3 4 1 
4 5 1 

$df3 
    v111 v222 
1 3 1 
2 4 1 
3 5 1 
4 6 1 
5 7 1 

如果你真的想覆盖之前的对象。

dat_list <- lapply(dat, FUN = function(x) x[complete.cases(x),]) 
df1 <- dat_list$df1 
df2 <- dat_list$df2 
df3 <- dat_list$df3 
+0

@charles,这将工作,但我正在寻找没有像你这样命名每个df,例如,不是'df1 < - dat_list $ df1' – 2014-08-28 19:40:34

1

这是你在找什么?

df <- lapply(
    names(df), 
    function(x){ 
    df[[x]][!(is.na(df[[x]][,1]) | df[[x]][,1]==""), ] 
    }) 

,让你

> df 
[[1]] 
    v1 v2 
1 1 1 
2 2 1 
3 3 1 

[[2]] 
    v11 v22 
1 2 1 
2 3 1 
3 4 1 
4 5 1 

[[3]] 
    v111 v222 
1 3 1 
2 4 1 
3 5 1 
4 6 1 
5 7 1 
+0

它可能比我所寻找的更好,因为它保持更新结果在列表中。但我想覆盖原来的数据框对象。 – 2014-08-28 19:38:26

0

检查你的新的数据帧,或者你可以使用assign

names1 <- paste0("df", 1:3) 
for(i in seq_along(names1)){ 
x <- get(names1[i]) 
x1 <- x[!(is.na(x[,1])|x[1]==''),] 
assign(names1[i], x1) 
} 

    df1 
    # v1 v2 
#1 1 1 
#2 2 1 
#3 3 1 

df2 
# v11 v22 
#1 2 1 
#2 3 1 
#3 4 1 
#4 5 1