删除数据框中的行,这些行在另一个数据框的相应行中具有特定值
Delete rows in a data frame that have a specific value in a corresponding row of another data frame
我有两个数据框。
第一个保存我的实际数据,我们称它为数据。第二个用作指示矩阵,它是使用 if-else 语句构造的,该语句检查是否出现一行至少包含 1 或 2 的值,我们称之为 indic.
这是一个例子:
col1<-c(1,3,1,3,2)
col2<-c(3,4,2,3,"")
col3<-c(1,3,"","","")
col4<-c(2,"","","","")
data<-data.frame(cbind(col1,col2,col3,col4))
> data
col1 col2 col3 col4
1 3 1 2
3 4 3
1 2
3 3
2
数据的行必须包含至少一个1或2,所以这是我的函数:
remove<-function(x){
if (((x[1] == "1") | (x[1] == "2")) | ((x[2] == "1") | (x[2] == "2"))
| ((x[3] == "1") | (x[3] == "2")) | ((x[4] == "1") | (x[4] == "2"))){
return(0)
}
else{
return(1)
}
}
indic<-data.frame(apply(data,1,remove))
> indic
y
1 0
2 1
3 0
4 1
5 0
查看数据,第2行和第4行至少不包含1或2,indic[=42=证实了这一点].
我想删除 data 中的第 2 行和第 4 行,它们对应于 indic 中的第 2 行和第 4 行。我已经尝试过以下方法:
finalMatrix<-class(array)
for(i in 1:nrow(indic)){
if (indic[i,1] == "1"){
finalMatrix = data[-i,]
}
else{
data[i,] = data[i,]
}
}
然而,我的输出是这样的:
> finalMatrix
col1 col2 col3 col4
1 3 1 2
3 4 3
1 2
2
这仅有效地消除了第四行。我认为这可能与我必须在每次迭代后创建一个新的数据框有关,但问题是迭代长度发生了变化。
想知道我的代码是否走在正确的轨道上...任何建议都会很好。一段时间以来我一直在想这个问题。
-苏菲
您可以尝试生成一个 TRUE/FALSE 向量而不是包含 0/1 的印度向量。这样最后的过滤效果更明显。
> data
col1 col2 col3 col4
1 1 3 1 2
2 3 4 3
3 1 2
4 3 3
5 2
使用 any
可以让您轻松访问 1
或 2
行的内容。如果满足两个条件之一,第二个 any
会告诉您。 apply()
遍历所有行,如果第二个参数设置为1.
indic <- apply(data, 1, function(row) {
any(c(any(row == 1), any(row == 2)))
})
> indic
[1] TRUE FALSE TRUE FALSE TRUE
> data[indic,]
col1 col2 col3 col4
1 1 3 1 2
3 1 2
5 2
正如您问题的标题所暗示的那样,indic-vector 也可以应用于另一个数据框,但这里重要的是要注意数据框和 indic-vector 具有相同的尺寸或目标用于矢量回收。
采纳@nicola 关于使用矢量化的建议。
data[rowSums(data=="1" | data=="2")>0,]
这将最有效地完成工作,节省循环并创建 indic
。尽管从 rowSums(data=="1" | data=="2")>0
发出的 TRUE/FALSE 向量仍然可以保存在变量中。
我有两个数据框。
第一个保存我的实际数据,我们称它为数据。第二个用作指示矩阵,它是使用 if-else 语句构造的,该语句检查是否出现一行至少包含 1 或 2 的值,我们称之为 indic.
这是一个例子:
col1<-c(1,3,1,3,2)
col2<-c(3,4,2,3,"")
col3<-c(1,3,"","","")
col4<-c(2,"","","","")
data<-data.frame(cbind(col1,col2,col3,col4))
> data
col1 col2 col3 col4
1 3 1 2
3 4 3
1 2
3 3
2
数据的行必须包含至少一个1或2,所以这是我的函数:
remove<-function(x){
if (((x[1] == "1") | (x[1] == "2")) | ((x[2] == "1") | (x[2] == "2"))
| ((x[3] == "1") | (x[3] == "2")) | ((x[4] == "1") | (x[4] == "2"))){
return(0)
}
else{
return(1)
}
}
indic<-data.frame(apply(data,1,remove))
> indic
y
1 0
2 1
3 0
4 1
5 0
查看数据,第2行和第4行至少不包含1或2,indic[=42=证实了这一点].
我想删除 data 中的第 2 行和第 4 行,它们对应于 indic 中的第 2 行和第 4 行。我已经尝试过以下方法:
finalMatrix<-class(array)
for(i in 1:nrow(indic)){
if (indic[i,1] == "1"){
finalMatrix = data[-i,]
}
else{
data[i,] = data[i,]
}
}
然而,我的输出是这样的:
> finalMatrix
col1 col2 col3 col4
1 3 1 2
3 4 3
1 2
2
这仅有效地消除了第四行。我认为这可能与我必须在每次迭代后创建一个新的数据框有关,但问题是迭代长度发生了变化。
想知道我的代码是否走在正确的轨道上...任何建议都会很好。一段时间以来我一直在想这个问题。
-苏菲
您可以尝试生成一个 TRUE/FALSE 向量而不是包含 0/1 的印度向量。这样最后的过滤效果更明显。
> data
col1 col2 col3 col4
1 1 3 1 2
2 3 4 3
3 1 2
4 3 3
5 2
使用 any
可以让您轻松访问 1
或 2
行的内容。如果满足两个条件之一,第二个 any
会告诉您。 apply()
遍历所有行,如果第二个参数设置为1.
indic <- apply(data, 1, function(row) {
any(c(any(row == 1), any(row == 2)))
})
> indic
[1] TRUE FALSE TRUE FALSE TRUE
> data[indic,]
col1 col2 col3 col4
1 1 3 1 2
3 1 2
5 2
正如您问题的标题所暗示的那样,indic-vector 也可以应用于另一个数据框,但这里重要的是要注意数据框和 indic-vector 具有相同的尺寸或目标用于矢量回收。
采纳@nicola 关于使用矢量化的建议。
data[rowSums(data=="1" | data=="2")>0,]
这将最有效地完成工作,节省循环并创建 indic
。尽管从 rowSums(data=="1" | data=="2")>0
发出的 TRUE/FALSE 向量仍然可以保存在变量中。