R 按条目筛选数据帧
如何根据数据框中任何位置的特定值筛选数据集,而不必在任何列或行下 假设我有一个这样的数据帧R 按条目筛选数据帧,r,dataframe,subset,R,Dataframe,Subset,如何根据数据框中任何位置的特定值筛选数据集,而不必在任何列或行下 假设我有一个这样的数据帧 id gender group Student_Math_1 Student_Math_2 Student_Read_1 Student_Read_2 46 M Red 23 45 37 56 46 M Red 34
id gender group Student_Math_1 Student_Math_2 Student_Read_1 Student_Read_2
46 M Red 23 45 37 56
46 M Red 34 36 33 78
46 M Red 56 63 58 NA
62 F Blue 59 NA NA 68
62 F Blue NA 68 87 73
38 M Red 78 57 NA 65
38 M Red NA 75 54 NA
17 F Blue 74 NA 56 72
17 F Blue 75 61 NA 79
17 F Blue NA 74 43 81
我试图对这个数据框进行子集划分,这样我就可以保留包含值68
的所有行和列,而不管它出现在数据框中的什么位置
最终结果将是
id gender group Student_Math_1 Student_Math_2 Student_Read_1 Student_Read_2
62 F Blue 59 NA NA 68
62 F Blue NA 68 87 73
欢迎任何提示或建议。提前谢谢
df = structure(list(id = c(46, 46, 46, 62, 62, 38, 38, 17, 17, 17),
gender = structure(c(2L, 2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L,
1L), .Label = c("F", "M"), class = "factor"), group = structure(c(2L,
2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 1L), .Label = c("Blue", "Red"
), class = "factor"), Student_Math_1 = c(23, 34, 56, 59,
NA, 78, NA, 74, 75, NA), Student_Math_2 = c(45, 36, 63, NA,
68, 57, 75, NA, 61, 74), Student_Read_1 = c(37, 33, 58, NA,
87, NA, 54, 56, NA, 43), Student_Read_2 = c(56, 78, NA, 68,
73, 65, NA, 72, 79, 81)), .Names = c("id", "gender", "group",
"Student_Math_1", "Student_Math_2", "Student_Read_1", "Student_Read_2"
), row.names = c(NA, -10L), class = "data.frame")
那么:
## use data from "Student_Math_1" column to "Student_Read_2" column
df[rowSums(df[4:7] == 68, na.rm = TRUE) > 0, ]
# id gender group Student_Math_1 Student_Math_2 Student_Read_1 Student_Read_2
#4 62 F Blue 59 NA NA 68
#5 62 F Blue NA 68 87 73
注意,df[4:7]==68
返回一个逻辑矩阵(使用NA
),我们使用NA.rm=TRUE
获取行和。在这种算术运算过程中,TRUE
被视为1,FALSE
被视为0
跟进
感谢Ben Bolker提醒您这一更具可读性的解决方案,如果您正在学习R:
df[apply(df[4:7] == 68, 1L, any, na.rm = TRUE), ]
它应用行方式any
(带na.rm=TRUE
)。我不记得在性能方面我在哪里比较了这两个。但我不会费心做一个快速的实验:
library(microbenchmark)
## For simplicity / neatness, I generate a logical matrix `X` without `NA`
X <- matrix(sample(c(TRUE, FALSE), 2000 * 10, replace = TRUE), 2000)
## also measuring 989's solution
microbenchmark(ZL = rowSums(X) > 0,
Ben = apply(X, 1L, any),
"989" = unique(which(X, arr.ind = T)[,1]))
#Unit: microseconds
# expr min lq mean median uq max neval cld
# ZL 144.24 149.76 183.3516 164.86 172.48 2077.80 100 a
# Ben 5610.08 5730.78 6003.0660 5779.20 5861.46 8021.72 100 c
# 989 1571.72 1639.58 2033.4224 1664.78 1721.18 5339.48 100 b
库(微基准)
##为了简单/整洁,我生成了一个逻辑矩阵'X',没有'NA'`
那么:
## use data from "Student_Math_1" column to "Student_Read_2" column
df[rowSums(df[4:7] == 68, na.rm = TRUE) > 0, ]
# id gender group Student_Math_1 Student_Math_2 Student_Read_1 Student_Read_2
#4 62 F Blue 59 NA NA 68
#5 62 F Blue NA 68 87 73
注意,df[4:7]==68
返回一个逻辑矩阵(使用NA
),我们使用NA.rm=TRUE
获取行和。在这种算术运算过程中,TRUE
被视为1,FALSE
被视为0
跟进
感谢Ben Bolker提醒您这一更具可读性的解决方案,如果您正在学习R:
df[apply(df[4:7] == 68, 1L, any, na.rm = TRUE), ]
它应用行方式any
(带na.rm=TRUE
)。我不记得在性能方面我在哪里比较了这两个。但我不会费心做一个快速的实验:
library(microbenchmark)
## For simplicity / neatness, I generate a logical matrix `X` without `NA`
X <- matrix(sample(c(TRUE, FALSE), 2000 * 10, replace = TRUE), 2000)
## also measuring 989's solution
microbenchmark(ZL = rowSums(X) > 0,
Ben = apply(X, 1L, any),
"989" = unique(which(X, arr.ind = T)[,1]))
#Unit: microseconds
# expr min lq mean median uq max neval cld
# ZL 144.24 149.76 183.3516 164.86 172.48 2077.80 100 a
# Ben 5610.08 5730.78 6003.0660 5779.20 5861.46 8021.72 100 c
# 989 1571.72 1639.58 2033.4224 1664.78 1721.18 5339.48 100 b
库(微基准)
##为了简单/整洁,我生成了一个逻辑矩阵'X',没有'NA'`
X或者
df[unique(which(df==68, arr.ind = T)[,1]),]
# id gender group Student_Math_1 Student_Math_2 Student_Read_1 Student_Read_2
#5 62 F Blue NA 68 87 73
#4 62 F Blue 59 NA NA 68
在这种情况下,您不需要关心列的位置或出现NA
s的位置<代码>唯一
用于每行出现一次以上的情况。或者
df[unique(which(df==68, arr.ind = T)[,1]),]
# id gender group Student_Math_1 Student_Math_2 Student_Read_1 Student_Read_2
#5 62 F Blue NA 68 87 73
#4 62 F Blue 59 NA NA 68
在这种情况下,您不需要关心列的位置或出现NA
s的位置unique
用于每行出现68次以上的情况。如果一行出现68次以上,则返回重复的行。@989,我发现这个解决方案非常简单,完全符合我的预期。如果68
连续出现多次,则返回重复的行。@989,我发现这个解决方案非常简单,完全符合我的预期。@989df[apply(df[,3:7]==68,1,any,na.rm=TRUE),]
,这并没有比这个解决方案更清楚。一般来说,我喜欢any()
/all()
的可读性(而不是对强制为0/1的逻辑进行数字操作),但在这种情况下,我同意这没有多大帮助。我认为,除非使用真正巨大的数据,否则像这样的行动的时间差异通常是微不足道的…@BenBolker-很有趣-我认为在时间方面会有更大的惩罚。在10万行上,差异仍然只是一秒钟的一小部分。如果行数超过100万行,可能会大幅增加。@ZheyuanLi,我只能删除我的评论。我已经做到了df[apply(df[,3:7]==68,1,any,na.rm=TRUE),]
,这并没有比这个解决方案更清楚。一般来说,我喜欢any()
/all()
的可读性(而不是对强制为0/1的逻辑进行数字操作),但在这种情况下,我同意这没有多大帮助。我认为,除非使用真正巨大的数据,否则像这样的行动的时间差异通常是微不足道的…@BenBolker-很有趣-我认为在时间方面会有更大的惩罚。在10万行上,差异仍然只是一秒钟的一小部分。如果行数超过100万行,可能会大幅增加。@ZheyuanLi,我只能删除我的评论。我已经这样做了。一般来说,您可以考虑从宽到长的形式重塑数据结构。第4列到第7列似乎包含所有相同类型的数据(等级?百分比?),而列标题看起来像属性(测试名称?)。宽表格通常是在Excel电子表格中收集数据时所得到的,但是长格式对于R中的数据操作或聚合通常更为方便。一般来说,您可以考虑将数据结构从宽格式改为长格式。第4列到第7列似乎包含所有相同类型的数据(等级?百分比?),而列标题看起来像属性(测试名称?)。在Excel电子表格中收集数据时,通常会得到宽格式,但在R中,长格式通常更便于数据操作或聚合。