我有一个data.frame,其中有几行来自合并,但并未完全合并:
b <- read.table(text = "
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
68 HA-09 16 <NA> <NA> <NA> 5 NA
69 HA-09 16 <33% no/occasional <NA> NA 1")
如何通过列合并它们?
预期产出:
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
69 HA-09 16 <33% no/occasional <NA> 5 1
请注意,某些列(ID除外)在两行上都具有相同的值。这些列不是数据库(AFAIK)的“主键”的一部分。所以如果有几个不同的值不应该合并。我试过的事情:
merge(b[1, ], b[2, ], all = T) # Doesn't merge the rows, just the data.frames
cast(b, ID ~ .) # I can count them but not merging them into a single row
aggregate(b, by = list("ID", "Age"), c) # Error
答案 0 :(得分:2)
虽然我确信可以使用dplyr
或tidyr
,但这是一个data.table
解决方案:
b <- read.table(text = "
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
68 HA-09 16 <NA> <NA> <NA> 5 NA
69 HA-09 16 <33% no/occasional <NA> NA 1",
na.strings = c("NA", "<NA>"))
keycols <- c("ID", "Age")
library(data.table)
b_dt <- data.table(b)
filter_nas <- function(x){
if(all(is.na(x))){
return(unique(x))
}
return(unique(x[!is.na(x)]))
}
b_dt[, lapply(.SD, filter_nas ), by = mget(keycols)]
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
1: HA-09 16 <33% no/occasional NA 5 1
请注意,这仅在密钥唯一时才有效。
答案 1 :(得分:2)
对于您提供的数据版本,以下是一个基本的R方法:
aggregate(b[-grep("^(ID|Age)$", names(b))], b[c("ID", "Age")],
FUN=function(x) if(all(is.na(x))) NA else x[!is.na(x)][1])
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
1 HA-09 16 <33% no/occasional NA 5 1
它使用aggregate
和if
else
支票。这将返回第一个不存在的元素(如果存在的话)。我拿第一个元素,因为至少有一个观察。代码中的i
可以替换为length(x)
以选择最后一个元素。
正如@jdobres在对另一个答案的评论中所建议的那样,可以将paste
与collapse参数结合使用来组合多个非缺失元素。当然,这会将矢量的类型转换为字符,如果变量是数字,这可能是不可取的。
注意:我编辑了我的原始答案,在密钥中包含“Age”,感谢@ sebastian-c指出这一点。
如果“年龄”不是密钥的一部分,那么
aggregate(b[-grep("^(ID)$", names(b))], b["ID"],
FUN=function(x) if(all(is.na(x))) NA else x[!is.na(x)][1])
会奏效。
数据强>
b <- read.table(text = "
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
68 HA-09 16 NA NA NA 5 NA
69 HA-09 16 <33% no/occasional NA NA 1")
答案 2 :(得分:2)
使用dplyr
的{{1}}方法:
summarise_all
该函数的定义是处理所有值为## using `na.strings` to identify NA entries in posted data
b <- read.table(text = "
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
68 HA-09 16 <NA> <NA> <NA> 5 NA
69 HA-09 16 <33% no/occasional <NA> NA 1", na.strings = c("NA", "<NA>"))
library(dplyr)
f <- function(x) {
x <- na.omit(x)
if (length(x) > 0) first(x) else NA
}
res <- b %>% group_by(ID,Age) %>% summarise_all(funs(f))
##Source: local data frame [1 x 7]
##Groups: ID [?]
##
## ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
## <fctr> <int> <fctr> <fctr> <lgl> <int> <int>
##1 HA-09 16 <33% no/occasional NA 5 1
的情况。
正如@jdobres建议的那样,如果要合并多个非NA
值(每列),您可能希望使用以下方法将所有这些值展平为字符串表示形式:
NA
在您发布的数据中,结果与上述相同,因为汇总的所有列最多只有一个非library(dplyr)
f <- function(x) {
x <- na.omit(x)
if (length(x) > 0) paste(x,collapse='-') else NA
}
res <- b %>% group_by(ID,Age) %>% summarise_all(funs(f))
值。
答案 3 :(得分:1)
如果给定的ID具有不同的列信息,Llopis要求保留两行,这使得问题复杂化。首先,让我们创建一些示例数据来说明这种情况:
b <- read.table(text = "ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
HA-09 16 <NA> <NA> <NA> 5 NA
HA-09 16 <33% no/occasional <NA> NA 1
HA-10 20 no <NA> <NA> 2 NA
HA-10 20 yes <NA> 0 NA NA",
na.strings = c("NA", "<NA>"), header = T)
ID Age Steatosis Mallory Lille_dico Lille_3 Bili.AHHS2cat
1 HA-09 16 <NA> <NA> NA 5 NA
2 HA-09 16 <33% no/occasional NA NA 1
3 HA-10 20 no <NA> NA 2 NA
4 HA-10 20 yes <NA> 0 NA NA
这仍然可以完成,但摘要的自定义功能(让我们称之为f
)变得有点复杂:
f <- function(x) {
x <- x[!is.na(x$value),]
if (nrow(x) > 0) {
y <- unique(x[colnames(x) != 'row.ID'])
y$row.ID <- 1:nrow(y)
return(y)
} else {
return(data.frame())
}
}
请注意,此函数引用了一个名为&#34; row.ID&#34;的列,我们将在应用该函数之前创建该列:
library(tidyverse) # gives access to dplyr and tidyr packages
b2 <- gather(b, variable, value, -ID, -Age) %>% # gather the many columns into a simplified key/value pair of columns (one called 'variable', the other, 'value') for each ID
group_by(ID, variable) %>% # perform subsequent operations per ID and variable
mutate(row.ID = 1:n()) %>% # add a row identifier
do(f(.)) %>% # apply our custom function
spread(variable, value, convert = T) %>% # un-gather the variable/value columns
ungroup # remove grouping metadata
ID Age row.ID Bili.AHHS2cat Lille_3 Lille_dico Mallory Steatosis
* <fctr> <int> <int> <int> <int> <int> <chr> <chr>
1 HA-09 16 1 1 5 NA no/occasional <33%
2 HA-10 20 1 NA 2 0 <NA> no
3 HA-10 20 2 NA NA NA <NA> yes