2つの行があるデータフレームがあります。
| code | name | v1 | v2 | v3 | v4 |
|------|-------|----|----|----|----|
| 345 | Yemen | NA | 2 | 3 | NA |
| 346 | Yemen | 4 | NA | NA | 5 |
これらの2つの行をマージする簡単な方法はありますか? 「346」の名前を「345」に変更すると、作業が簡単になりますか?
aggregate
を使用できます。列name
で同じ値の行をマージするとします。
_aggregate(x=DF[c("v1","v2","v3","v4")], by=list(name=DF$name), min, na.rm = TRUE)
name v1 v2 v3 v4
1 Yemen 4 2 3 5
_
これはSQLSELECT name, min(v1) GROUP BY name
のようなものです。 min
関数は任意です。max
またはmean
を使用することもできます。これらはすべて、NAから非NA値を返し、_na.rm = TRUE
_。 (SQLのようなcoalesce()
関数は、Rに存在する場合、より良い音になります。)
ただし、最初に、特定のname
のすべての非NA値が同一であるかどうかを確認する必要があります。たとえば、aggregate
をmin
とmax
の両方で実行して比較するか、range
で実行します。
最後に、v1-4だけでなく多くの変数がある場合は、DF[,!(names(DF) %in% c("code","name"))]
を使用して列を定義できます。
完全を期すためにdplyr
&_data.table
_ソリューションを追加
dplyr::coalesce()
を使用
_library(dplyr)
sum_NA <- function(x) {if (all(is.na(x))) x[NA_integer_] else sum(x, na.rm = TRUE)}
df %>%
group_by(name) %>%
summarise_all(sum_NA)
#> # A tibble: 1 x 6
#> name code v1 v2 v3 v4
#> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Yemen 691 4 2 3 5
# Ref: https://stackoverflow.com/a/45515491
# Supply lists by splicing them into dots:
coalesce_by_column <- function(df) {
return(dplyr::coalesce(!!! as.list(df)))
}
df %>%
group_by(name) %>%
summarise_all(coalesce_by_column)
#> # A tibble: 1 x 6
#> name code v1 v2 v3 v4
#> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 Yemen 345 4 2 3 5
_
_data.table
_を使用
_# Ref: https://stackoverflow.com/q/28036294/
library(data.table)
setDT(df)[, lapply(.SD, na.omit), by = name]
#> name code v1 v2 v3 v4
#> 1: Yemen 345 4 2 3 5
#> 2: Yemen 346 4 2 3 5
setDT(df)[, code := NULL][, lapply(.SD, na.omit), by = name]
#> name v1 v2 v3 v4
#> 1: Yemen 4 2 3 5
setDT(df)[, code := NULL][, lapply(.SD, sum_NA), by = name]
#> name v1 v2 v3 v4
#> 1: Yemen 4 2 3 5
_