如何在删除 NA 值时将多条记录合并为一条记录
How to collapse many records into one while removing NA values
假设我有以下数据框df
name <- c("Bill", "Rob", "Joe", "Joe")
address <- c("123 Main St", "234 Broad St", NA, "456 North Ave")
favteam <- c("Dodgers", "Mets", "Pirates", NA)
df <- data.frame(name = name,
address = address,
favteam = favteam)
df
看起来像:
name address favteam
1 Bill 123 Main St Dodgers
2 Rob 234 Broad St Mets
3 Joe <NA> Pirates
4 Joe 456 North Ave <NA>
我想要做的是按名称折叠(合并)行(或通常,任意数量的分组变量)并具有除 NA
之外的任何其他值替换 NA
最终数据中的值,如下所示:
df_collapse <- foo(df)
name address favteam
1 Bill 123 Main St Dodgers
2 Rob 234 Broad St Mets
3 Joe 456 North Ave Pirates
这是 dplyr 的一个选项:
library(dplyr)
df %>%
group_by(name) %>%
summarise_each(funs(first(.[!is.na(.)]))) # or summarise_each(funs(first(na.omit(.))))
#Source: local data frame [3 x 3]
#
# name address favteam
#1 Bill 123 Main St Dodgers
#2 Joe 456 North Ave Pirates
#3 Rob 234 Broad St Mets
与 data.table:
library(data.table)
setDT(df)[, lapply(.SD, function(x) x[!is.na(x)][1L]), by = name]
# name address favteam
#1: Bill 123 Main St Dodgers
#2: Rob 234 Broad St Mets
#3: Joe 456 North Ave Pirates
或
setDT(df)[, lapply(.SD, function(x) head(na.omit(x), 1L)), by = name]
编辑:
你说在你的实际数据中每个名字有不同数量的非 NA 响应。在这种情况下,以下方法可能会有所帮助。
考虑这个修改后的示例数据(查看最后一行):
name <- c("Bill", "Rob", "Joe", "Joe", "Joe")
address <- c("123 Main St", "234 Broad St", NA, "456 North Ave", "123 Boulevard")
favteam <- c("Dodgers", "Mets", "Pirates", NA, NA)
df <- data.frame(name = name,
address = address,
favteam = favteam)
df
# name address favteam
#1 Bill 123 Main St Dodgers
#2 Rob 234 Broad St Mets
#3 Joe <NA> Pirates
#4 Joe 456 North Ave <NA>
#5 Joe 123 Boulevard <NA>
然后,您可以使用这种 data.table 方法来获取非 NA 响应,这些响应的数量可能因名称而异:
setDT(df)[, lapply(.SD, function(x) unique(na.omit(x))), by = name]
# name address favteam
#1: Bill 123 Main St Dodgers
#2: Rob 234 Broad St Mets
#3: Joe 456 North Ave Pirates
#4: Joe 123 Boulevard Pirates
假设我有以下数据框df
name <- c("Bill", "Rob", "Joe", "Joe")
address <- c("123 Main St", "234 Broad St", NA, "456 North Ave")
favteam <- c("Dodgers", "Mets", "Pirates", NA)
df <- data.frame(name = name,
address = address,
favteam = favteam)
df
看起来像:
name address favteam
1 Bill 123 Main St Dodgers
2 Rob 234 Broad St Mets
3 Joe <NA> Pirates
4 Joe 456 North Ave <NA>
我想要做的是按名称折叠(合并)行(或通常,任意数量的分组变量)并具有除 NA
之外的任何其他值替换 NA
最终数据中的值,如下所示:
df_collapse <- foo(df)
name address favteam
1 Bill 123 Main St Dodgers
2 Rob 234 Broad St Mets
3 Joe 456 North Ave Pirates
这是 dplyr 的一个选项:
library(dplyr)
df %>%
group_by(name) %>%
summarise_each(funs(first(.[!is.na(.)]))) # or summarise_each(funs(first(na.omit(.))))
#Source: local data frame [3 x 3]
#
# name address favteam
#1 Bill 123 Main St Dodgers
#2 Joe 456 North Ave Pirates
#3 Rob 234 Broad St Mets
与 data.table:
library(data.table)
setDT(df)[, lapply(.SD, function(x) x[!is.na(x)][1L]), by = name]
# name address favteam
#1: Bill 123 Main St Dodgers
#2: Rob 234 Broad St Mets
#3: Joe 456 North Ave Pirates
或
setDT(df)[, lapply(.SD, function(x) head(na.omit(x), 1L)), by = name]
编辑:
你说在你的实际数据中每个名字有不同数量的非 NA 响应。在这种情况下,以下方法可能会有所帮助。
考虑这个修改后的示例数据(查看最后一行):
name <- c("Bill", "Rob", "Joe", "Joe", "Joe")
address <- c("123 Main St", "234 Broad St", NA, "456 North Ave", "123 Boulevard")
favteam <- c("Dodgers", "Mets", "Pirates", NA, NA)
df <- data.frame(name = name,
address = address,
favteam = favteam)
df
# name address favteam
#1 Bill 123 Main St Dodgers
#2 Rob 234 Broad St Mets
#3 Joe <NA> Pirates
#4 Joe 456 North Ave <NA>
#5 Joe 123 Boulevard <NA>
然后,您可以使用这种 data.table 方法来获取非 NA 响应,这些响应的数量可能因名称而异:
setDT(df)[, lapply(.SD, function(x) unique(na.omit(x))), by = name]
# name address favteam
#1: Bill 123 Main St Dodgers
#2: Rob 234 Broad St Mets
#3: Joe 456 North Ave Pirates
#4: Joe 123 Boulevard Pirates