R:子集数据以创建三个新的子集-使用subset(),function或if / then有条件

时间:2018-07-31 21:17:33

标签: r filter subset

我一直在尝试以更加细微的方式对数据进行子集化,以避免过多的冗长和冗余。我发现最终要为子集输入复杂的条件,如果要创建数据框的多个子集,这种方法不可行。

数据:

> print(assm)
Speaker V1 POA V2
1     JF01  u  tt  U
2     JF01  o   r  a
3     JF01  o   t  a
4     JF01  a   r  u
5     JF01  e   l  i
6     JF01  a   j  o
7     JF01  e   s  o
8     JF01  u   l  i
9     JF01  a   j  i
10    JF01  i   y  a
11    JF01  o   g  i
12    JF01  u   m  O
13    JF01  u   l  E
14    JF01  a   t  o
15    JF01  o   r  u
16    JF01  a   l  e
17    JF01  u  tt  o
18    JF01  o   r  a
19    JF01  o   t  a
20    JF01  a   r  u
21    JF01  e   l  i
22    JF01  i   y  O
23    JF01  o   r  i
24    JF01  i   l  E
25    JF01  u   k  o
26    JF01  o   n  e
27    JF01  a   t  o
28    JF01  o   r  u
29    JF01  o   r  a
30    JF01  u   m  u
31    JF01  u   l  a
32    JF01  a   t  u
33    JF01  u  tt  o
34    JF01  o   r  a
35    JF01  o   t  a
36    JF01  a   h  e
37    JF01  u   r  e
38    JF01  o   l  i
39    JF01  i   b  o
40    JF01  o   l  e
41    JF01  e   j  u
42    JF01  a   l  e
43    JF01  u  tt  i
44    JF01  o   t  a
45    JF01  a   r  u
46    JF01  e   l  i
47    JF01  i   y  U
48    JF01  o   r  i
49    JF01  i   l  e
50    JF01  u   k  o 

我使用subset()和data []在以下条件下创建了3个子集:

assm <- subset(assm, V1==“a"| V1=="e"| V1=="E"| V1=="i"| V1=="o"| V1=="O"| V1=="u"| V1=="U", select = Speaker:V2)
assm <- subset(assm, V2==“a”| V2==“e”| V2=="E"| V2=="i"| V2=="o"| V2=="O"| V2=="u"| V2=="U", select = Speaker:V2)

是否有一种更有效的方法(例如,使用正则表达式进行子集设置)来避免所有的硬编码(例如使用变量)? V1和V2的子设置条件是相同的,但是我最终两次输入了内容。

使用非常基本的R,这是我所做的更多子设置:

assm_h <- subset(assm, (V1=="o" & V2=="i")|
                     (V1=="e" & V2=="i")|
                     (V1=="u" & V2=="i")|
                     (V1=="e" & V2=="u")|
                     (V1=="o" & V2=="u")|
                     (V1=="u" & V2=="u"))

assm_nh <- subset(assm, (V1=="i" & V2=="O")|
                      (V1=="i" & V2=="E")|
                      (V1=="i" & V2=="U")|
                      (V1=="u" & V2=="O")|
                      (V1=="u" & V2=="E")|
                      (V1==“u" & V2=="U"))

我还需要一个子集(assm_neu),其中一个子集所包含的行与assm_h和assm_nh子集所满足的条件(即其余数据)不匹配,该任务需要更艰苦的编码。我的方法需要艰苦的打字和多个步骤。

是否有一种方法可以使此任务更高效,从而使子集不仅返回所要求的内容,还返回不满足条件的数据子集?我已经阅读了多篇有关函数和条件的文章,但是没有哪一篇文章可以帮助我用一个命令提取和创建多个数据集?

先谢谢了。 [编辑:语法]

3 个答案:

答案 0 :(得分:0)

不确定到底要获得什么灵活性,但这是我将如何处理另外两个子设置的情况:

library(tibble)
library(dplyr)
library(magrittr)

首先,我将您的数据读为tibble数据框:

> df <- as.tibble(read.table("temp.txt",header=TRUE))

设置我们要寻找的V1V2的组合:

combos <- c("oi","ei","ui","eu","ou","uu")

现在创建一个临时变量V1V2

> df %>% mutate(V1V2=paste0(V1,V2))
# A tibble: 50 x 6
       x Speaker V1    POA   V2    V1V2 
   <int> <fct>   <fct> <fct> <fct> <chr>
 1     1 JF01    u     tt    U     uU   
 2     2 JF01    o     r     a     oa   
 3     3 JF01    o     t     a     oa   
 4     4 JF01    a     r     u     au   
 5     5 JF01    e     l     i     ei   
 6     6 JF01    a     j     o     ao   
 7     7 JF01    e     s     o     eo   
 8     8 JF01    u     l     i     ui   
 9     9 JF01    a     j     i     ai   
10    10 JF01    i     y     a     ia   
# ... with 40 more rows

然后查找满足条件的行(其中只有13条):

> df[z$V1V2 %in% combos,]
# A tibble: 13 x 5
       x Speaker V1    POA   V2   
   <int> <fct>   <fct> <fct> <fct>
 1     5 JF01    e     l     i    
 2     8 JF01    u     l     i    
 3    11 JF01    o     g     i    
 4    15 JF01    o     r     u    
 5    21 JF01    e     l     i    
 6    23 JF01    o     r     i    
 7    28 JF01    o     r     u    
 8    30 JF01    u     m     u    
 9    38 JF01    o     l     i    
10    41 JF01    e     j     u    
11    43 JF01    u     tt    i    
12    46 JF01    e     l     i    
13    48 JF01    o     r     i    

如果要查找不满足这些条件的行(其中37条),则:

> '%ni%' <- Negate('%in%')
> df[!(z$V1V2 %ni% combos),]
# A tibble: 37 x 5
       x Speaker V1    POA   V2   
   <int> <fct>   <fct> <fct> <fct>
 1     1 JF01    u     tt    U    
 2     2 JF01    o     r     a    
 3     3 JF01    o     t     a    
 4     4 JF01    a     r     u    
 5     6 JF01    a     j     o    
 6     7 JF01    e     s     o    
 7     9 JF01    a     j     i    
 8    10 JF01    i     y     a    
 9    12 JF01    u     m     O    
10    13 JF01    u     l     E    
# ... with 27 more rows

答案 1 :(得分:0)

考虑使用split来构建包含 V1 V2 的所有组合的数据帧列表。然后,使用do.call将数据框子集的名称按列表子集,以将所有子集附加在一起:

df_list <- split(assm, assm[c("V1", "V2")])
names(df_list)
# [1] "a.a" "e.a" "i.a" "o.a" "u.a" "a.e" "e.e" "i.e" "o.e" "u.e" "a.E" "e.E" "i.E" "o.E" "u.E" "a.i" "e.i" "i.i" "o.i"
# [20] "u.i" "a.o" "e.o" "i.o" "o.o" "u.o" "a.O" "e.O" "i.O" "o.O" "u.O" "a.u" "e.u" "i.u" "o.u" "u.u" "a.U" "e.U" "i.U"
# [39] "o.U" "u.U"

# CONDITION VECTORS
cond_1 <- c("o.i", "e.i", "u.i", "e.u", "o.u", "u.u")
cond_2 <- c("i.O", "i.E", "i.U", "u.O", "u.E", "u.U")

# FIRST SUBSET
assm_h2 <- do.call(rbind, unname(df_list[cond_1]))
assm_h2 <- with(assm_h2, assm_h2[order(V1, V2),])

# SECOND SUBSET
assm_nh2 <- do.call(rbind, unname(df_list[cond_2]))
assm_nh2 <- with(assm_nh2, assm_nh2[order(V1, V2),])

# THIRD SUBSET (NOT IN EITHER LIST ABOVE)
assm_neu <- do.call(rbind, unname(df_list[!(names(df_list) %in% c(cond_1, cond_2))]))

作为测试,重新排列 V1 V2 列后,上述前两个等同于OP的原件:

assm_h <- subset(assm, (V1=="o" & V2=="i")|
                   (V1=="e" & V2=="i")|
                   (V1=="u" & V2=="i")|
                   (V1=="e" & V2=="u")|
                   (V1=="o" & V2=="u")|
                   (V1=="u" & V2=="u"))

assm_h <- with(assm_h, assm_h[order(V1, V2),])

identical(assm_h, assm_h2)
# [1] TRUE

assm_nh <- subset(assm, (V1=="i" & V2=="O")|
                    (V1=="i" & V2=="E")|
                    (V1=="i" & V2=="U")|
                    (V1=="u" & V2=="O")|
                    (V1=="u" & V2=="E")|
                    (V1=="u" & V2=="U"))

assm_nh <- with(assm_nh, assm_nh[order(V1, V2),])

identical(assm_nh, assm_nh2)
# [1] TRUE

答案 2 :(得分:0)

r2evans正确地指出,GREP是子集数据的最简单方法。感谢@mysteRious建议使用临时列V1V2。我意识到有一种方法可以不用临时列。

这里是一个想法:

    attach(assm)
assm_h <- assm[grepl("^oi$|^ei$|^ui$|^eu$|^ou$|^uu$",(paste(assm$V1,assm$V2, sep=""))), ]
assm_nh <- assm[grepl("^iO$|^iE$|^iU$|^uO$|^uE$|^uU$",(paste(assm$V1,assm$V2, sep=""))), ]
assm_neu <- assm[!(grepl("^oi$|^ei$|^ui$|^eu$|^ou$|^uu$",(paste(assm$V1,assm$V2, sep=""))) | (grepl("^iO$|^iE$|^iU$|^uO$|^uE$|^uU$",(paste(assm$V1,assm$V2, sep=""))))), ]

从逻辑上讲,第三种情况是“或非”条件:既不满足两个条件又不需要同时满足两个条件的行。