【问题标题】:R - interactive subsetting of rows by vector of column headersR - 通过列标题向量对行进行交互式子集
【发布时间】:2016-12-15 18:35:02
【问题描述】:

我有 2 个不同的数据框,格式如下:

DF1 -

  v1 v2 v3 v4 v5
a 1  2  +
b 5  2  +  +
c 5  2  +     +
d 4  3     +  +
e 1  5  +     +
f 3  5 
g 4  2  
h 3  1  
i 5  5  +     +

DF2 -

  v1 v2 v3 v4 
a 1  2  +
b 5  2  +  +
c 5  2  +     
d 4  3     +  
e 1  5  +     
f 3  5 
g 4  2  
h 3  1  
i 5  5  +     

我的脚本给出了 v1 和 v2 的散点图,但首先我删除了 v3-v4 或 v3-v5 中至少有一个“+”的行。

我的数据框可以使用更多的 v1-v2 对更大,但总是有 v3-v4 或 v3-v5 列带有“+”。我手动调整代码以指定要绘制的列以及要删除的行,具体取决于我正在处理的 DF 格式。

效果很好,但我想让脚本更具交互性,如下所示:

# Select v3-v4 or v3-v5 via interactive gui to give vector of column headers.
remove.vars.vector <- select.list(names(DF), # Select columns as vector of column header names via interactive gui.
                           multiple = TRUE, # Can choose multiple columns.
                           title = "Choose variables to remove from data set", # Title on gui.
                           graphics = TRUE) # Allow launch of gui.

# Return columns from DF with this vector of column headers.
remove.vars.subset <- DF[remove.vars.vector]
# Return rows that have at least one "+" in v3-v4 or v3-v5.
remove.vars.subset.+ <- subset(DF, remove.vars.subset == "+")
# Removes all rows that contain >=1 NA.
complete.data.+ <- remove.vars.subset.+[complete.cases(remove.vars.subset.+), ] 
# Combine by rows "complete.data.+" with DF.
combo.list <- rbind(DF,complete.data.+)
# Remove duplicate rows from combined data frame.
complete.data <- combo.list[!duplicated(combo.list, fromLast = FALSE) & !duplicated(combo.list, fromLast = TRUE),]

问题:上述代码并未完全剥离 v3-4 或 v3-5 中至少包含一个“+”的行的数据框。问题似乎是这些行:

# Return rows that have at least one "+" in v3-v4 or v3-v5.
    remove.vars.subset.+ <- subset(DF, remove.vars.subset == "+")

最后我还得到了一些行,每个单元格中只有 NA,因此在下一行代码中完成了。

因此,最终的数据帧在 v3-4 或 v3-5 中仍然包含一些带有“+”的行。

问题

有没有更好的方法来使用列标题向量(行中可能包含“+”)来对数据框中的行进行子集化?

提前谢谢你。

编辑 - 09/08/2016 - 18:54 我只是注意到一些我没有澄清我的数据框的东西。有些行在 v3-v4 或 v3-v5 中没有“+”。这些是我最终想要保留的行,以便绘制散点图。我已经相应地编辑了数据框。我只是在寻找答案以尝试理解它们。我对 R 还是很陌生。

【问题讨论】:

    标签: r user-interface subset


    【解决方案1】:

    假设您的数据 DF

    > DF
      v1 v2 v3 v4 v5
    1  1  2  +      
    2  5  2  +  +   
    3  5  2  +     +
    4  4  3     +  +
    5  1  5  +     +
    

    我选择v3v4。然后remove.vars.subset,按照你的代码,是

    > remove.vars.subset
      v3 v4
    1  +   
    2  +  +
    3  +   
    4     +
    5  +   
    

    注意remove.vars.subset == "+" 的计算结果为

    > remove.vars.subset == "+"
            v3    v4
    [1,]  TRUE FALSE
    [2,]  TRUE  TRUE
    [3,]  TRUE FALSE
    [4,] FALSE  TRUE
    [5,]  TRUE FALSE
    

    然后subset 正在做的是要求R 从条件评估为TRUE 的数据框中返回行,即:

    DF[c(TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE),]

    连接第一列和第二列。但是数据框中只有 5 行,而逻辑向量中有 10 个元素。由于 DF 只有 5 行,所以附加了 NAs(所以就好像 DF 有 10 行)并相应地评估表达式。所以你看:

    > subset(DF, remove.vars.subset == "+")
         v1 v2   v3   v4   v5
    1     1  2    +          
    2     5  2    +    +     
    3     5  2    +         +
    5     1  5    +         +
    NA   NA NA <NA> <NA> <NA>
    NA.1 NA NA <NA> <NA> <NA>
    

    你可能想尝试的是

    DF[!apply(remove.vars.subset, MAR=1, function(x) any(x=="+")), ]
    > DF[!apply(remove.vars.subset, MAR=1, function(x) any(x=="+")), ]
    [1] v1 v2 v3 v4 v5
    <0 rows> (or 0-length row.names)
    

    它不返回任何行,因为所有行(给定v3v4 的选择)都至少有一个“+”。但是假设我们选择了v4v5

    > DF[!apply(remove.vars.subset, MAR=1, function(x) any(x=="+")), ]
      v1 v2 v3 v4 v5
    1  1  2  +   
    

    【讨论】:

    • 刚刚试过你的建议,效果很好。您正确地推测某些行没有“+”(在尝试您的建议之前,我编辑了我的帖子)。 Apply 函数系列已移至我要在 R 中探索的内容列表的顶部。非常感谢您的快速响应。
    • PS:我通过将我的原始方法数据框与您的修改产生的行绑定来验证,然后删除重复的行。答案是没有行的数据框....太棒了。我的大脑正在慢慢接受 R 编程逻辑!
    【解决方案2】:

    我有一个解决方案,您不选择列,而是从数据框中删除所有带有“+”和 NA 的行。我不知道这是否有帮助。 它基于以下问题: Better way to filter a data frame with dplyr using OR?

    v1 <- c(1,2,3,4,5,NA)
    v2 <- c(1,2,3,4,5,NA)
    v3 <- c("","+","+","","",NA)
    v4 <- c("","+","","+","",NA)
    v5 <- c("","+","","","",NA)
    
    D1 <- cbind.data.frame(v1,v2,v3,v4,v5,stringsAsFactors=F)
    
    library(dplyr)
    
    remove.vars.vector <- c("v3","v4","v5")
    condition <- c("+",NA)
    
    D1 %>%
      filter(rowSums(sapply(D1, FUN = "%in%", condition)) == 0) -> D1_new
    

    编辑: 我找到了选择列的可能性,不幸的是我没有找到按字符向量选择列的解决方案:

    D1 %>% select_(remove.vars.vector) -> D1_sub # NOT working
    
    D1 %>% select(v3:v5) -> D1_sub # working
    D1 %>% select(v3,v4,v5) -> D1_sub # working
    D1 %>% select_("v3","v4","v5") -> D1_sub # working
    
    D1 %>%
      filter(rowSums(sapply(D1_sub, FUN = "%in%", condition)) == 0) -> D1_new
    

    【讨论】:

    猜你喜欢
    • 2016-12-01
    • 2018-09-07
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多