[英]Remove rows from dataframe if they contain a certain value (R ,dplyr)
[英]Function to remove certain rows from dataframe
我正在嘗試編寫一個從數據框中刪除某些行的函數。 為簡單起見,讓我們假設要刪除的條件是該行中至少有一個NA。
df = data.frame(c("A","B","C"),c(1,NA,3))
fn = function (d) {
for (x in 1:nrow(d)) { for (y in 1:ncol(d)) {
if(is.na(d[x,y])) d = d[-x,]
}}}
fn(df)
PS:我知道有更好的方法來刪除行號至少為1的NA,即df = df [-which(!complete.cases(df)],但我很想知道為什么我編寫的代碼不起作用。
您需要從函數中顯式返回d
df <- data.frame(X1 = c("A","B","C"), X2 = c(1,NA,3))
fn <- function (d) {
for (x in 1:nrow(d)) {
for (y in 1:ncol(d)) {
if(is.na(d[x,y])) d = d[-x,]
}
}
d # return d
}
fn(df)
> fn(df)
X1 X2
1 A 1
3 C 3
R隱式返回最后一個操作的結果,但這是對第三行的if (...)
進行評估的結果,該行返回NULL
> foo <- fn(df) # using your fn()
> foo
NULL
您可以在函數末尾顯式調用return(d)
,但是由於R還在最后一條語句上調用return()
,就像調用return(return(d))
。 結果,您可以僅在函數的最后一行使用d
,而R做正確的事情。
不使用return()
的主要例外(即何時應使用它)是在您可能想從函數中盡早返回的情況下。
最后,不要只遍歷對象的行和列,而要考慮按行工作。 R是向量化的,因此您可以在整行上執行is.na()
(例如),然后if()
語句將是if (any(is.na(d[i, ]))
,其中i
是循環索引,例如:
fn2 <- function (d) {
for (i in 1:nrow(d)) {
if (any(is.na(d[i,]))) {
d <- d[-i, ]
}
}
d # return d
}
> fn2(df)
X1 X2
1 A 1
3 C 3
甚至有更有效的方法來執行此操作,但是如果您以向量化的方式思考,您將開始編寫更簡單,更快速的R代碼。
函數式編程風格
我認為OP缺少的是您不能直接修改作為參數傳遞的變量。 那是函數式編程風格。
訪問https://en.wikipedia.org/wiki/Functional_programming
實際上,函數主體中的變量是作為參數傳遞的變量的副本。 因此,您正在處理副本。
這就是為什么您必須返回副本並將其重新分配給變量的原因。
df <- data.frame(X1 = c("A","B","C"), X2 = c(1,NA,3))
fn <- function (d) {
for (x in 1:nrow(d)) {
for (y in 1:ncol(d)) {
if(is.na(d[x,y])) d = d[-x,]}}
d} # return d
df <- fn(df)
df
現在如OP所願
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.