簡體   English   中英

如何使用R中的自定義函數聚合data.frame中的多個列?

[英]How can I aggregate multiple columns in a data.frame with a custom function in R?

我有一個帶有一些重復鍵和缺少數據的data.frame dt ,即

Name     Height     Weight   Age
Alice    180        NA       35
Bob      NA         80       27
Alice    NA         70       NA
Charles  170        75       NA

在這種情況下,鍵是名稱,我想在每列中應用一個函數

f <- function(x){
  x <- x[!is.na(x)]
  x <- x[1]
  return(x)
  }

在通過密鑰(即“名稱”列)聚合時,以便獲得結果

Name     Height     Weight   Age
Alice    180        70       35
Bob      NA         80       27
Charles  170        75       NA

我試過了

dt_agg <- aggregate(. ~ Name,
                    data = dt,
                    FUN = f)

我有一些錯誤,然后我嘗試了以下

dt_agg_1 <- aggregate(Height ~ Name,
                      data = dt,
                      FUN = f)

dt_agg_2 <- aggregate(Weight ~ Name,
                      data = dt,
                      FUN = f)

這次它奏效了。

由於我有50列,第二種方法對我來說非常麻煩。 有沒有辦法解決第一種方法?

感謝幫助!

你非常接近aggregate函數,你需要調整聚合處理NA (從na.omitna.pass )。 我的猜測是聚合首先刪除NA的所有行,然后進行聚合,而不是刪除NAs,因為聚合迭代要聚合的列。 由於您的示例數據幀在每行中都有一個NA ,因此最終會得到一個0行數據幀(這是我在運行代碼時遇到的錯誤)。 我通過刪除除了一個NA以外的所有NA來測試它,並且您的代碼按原樣運行。 所以我們設置na.action = na.pass來傳遞NA。

dt_agg <- aggregate(. ~ Name,
                    data = dt,
                    FUN = f, na.action = "na.pass")

原始答案

dt_agg <- aggregate(dt[, -1], 
                    by = list(dt$Name),
                    FUN = f)
dt_agg
# Group.1 Height Weight Age
# 1   Alice    180     70  35
# 2     Bob     NA     80  27
# 3 Charles    170     75  NA

您可以使用dplyr執行此dplyr

library(dplyr)
df %>%
  group_by(Name) %>%
  summarize_all(funs(sort(.)[1]))

結果:

# A tibble: 3 x 4
     Name Height Weight   Age
   <fctr>  <int>  <int> <int>
1   Alice    180     70    35
2     Bob     NA     80    27
3 Charles    170     75    NA

數據:

df = read.table(text = "Name     Height     Weight   Age
Alice    180        NA       35
Bob      NA         80       27
Alice    NA         70       NA
Charles  170        75       NA", header = TRUE)

這是data.table一個選項

library(data.table)
setDT(df)[, lapply(.SD, function(x) head(sort(x), 1)), Name]
#      Name Height Weight Age
#1:   Alice    180     70  35
#2:     Bob     NA     80  27
#3: Charles    170     75  NA

只需在aggregate()調用中添加na.action=na.pass

aggdf <- aggregate(.~Name, data=df, FUN=f, na.action=na.pass)
#      Name Height Weight Age
# 1   Alice    180     70  35
# 2     Bob     NA     80  27
# 3 Charles    170     75  NA

如果向函數添加ifelse()以確保函數在所有值都為NA返回值:

f <- function(x) {
  x <- x[!is.na(x)]
  ifelse(length(x) == 0, NA, x)
}

您可以使用dplyr進行聚合:

library(dplyr)
dt %>% group_by(Name) %>% summarise_all(funs(f))

返回:

# A tibble: 3 x 4
     Name Height Weight   Age
   <fctr>  <dbl>  <dbl> <dbl>
1   Alice    180     70    35
2     Bob     NA     80    27
3 Charles    170     75    NA

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM