2017-08-07 14 views
1

ある場合は、1つの列が重複している行を削除data.tableを例data.tableR別の列は、ここでNA

dt <- data.table(col1 = c('A', 'A', 'B', 'C', 'C', 'D'), col2 = c(NA, 'dog', 'cat', 'jeep', 'porsch', NA)) 

    col1 col2 
1: A  NA 
2: A dog 
3: B cat 
4: C jeep 
5: C porsch 
6: D  NA 

である私は、COL2はNAであり、非を持っている場合COL1が重複している行を削除します別の行の-NA値。 AKAグループcol1で、グループに複数の行があり、そのうちの1つがNAである場合は、それを削除します。これはdtため、結果、次のようになります。

col1 col2 
2: A dog 
3: B cat 
4: C jeep 
5: C porsch 
6: D  NA 

私はこれを試してみました:私は

dt[, list(col2 = ifelse(length(col1>1), col2[!is.na(col2)], col2)), by=col1] 

    col1 col2 
1: A dog 
2: B cat 
3: C jeep 
4: D NA 

何をしないのですか?ありがとうございます

答えて

2

グループ内のすべてのNA例を見つけるための試みを、と:あなたは非NASが存在しているグループからNA値を削除したい場合は、if/elseを使用することができますそれらの行を削除します。私は誰かがすぐにでも迅速バージョンを上げるために起こっていると確信しているものの

dt[-dt[, .I[any(!is.na(col2)) & is.na(col2)], by=col1]$V1] 
# col1 col2 
#1: A dog 
#2: B cat 
#3: C jeep 
#4: C porsch 
#5: D  NA 

は、より速いようだ:

set.seed(1) 
dt2 <- data.table(col1=sample(1:5e5,5e6,replace=TRUE), col2=sample(c(1:8,NA),5e6,replace=TRUE)) 
system.time(dt2[-dt2[, .I[any(!is.na(col2)) & is.na(col2)], by=col1]$V1]) 
# user system elapsed 
# 1.49 0.02 1.51 
system.time(dt2[, .(col2 = if(all(is.na(col2))) NA_integer_ else na.omit(col2)), by = col1]) 
# user system elapsed 
# 4.49 0.04 4.54 
2

かっこが間違っています(たぶん、タイプミス)、私はそれがlength(col1) > 1であるはずです。また、スカラー条件ではifelseを使用していますが、これは期待通りに機能しません(ベクトルの最初の要素のみが選択されます)。その後も非NA値がある場合

dt[, .(col2 = if(all(is.na(col2))) NA_character_ else na.omit(col2)), by = col1] 

# col1 col2 
#1: A dog 
#2: B cat 
#3: C jeep 
#4: C porsch 
#5: D  NA 
3

group by col1の場合、グループに複数の行があり、そのうちの1つがNAである場合は、削除します。

抗結合を使用:

dt[!dt[, if (.N > 1L) .SD[NA_integer_], by=col1], on=names(dt)] 

    col1 col2 
1: A dog 
2: B cat 
3: C jeep 
4: C porsch 
5: D  NA 

@thelaからベンチマーク、ない(完全)が存在しないと仮定は、元のデータにdupes:

set.seed(1) 
dt2a <- data.table(col1=sample(1:5e5,5e6,replace=TRUE), col2=sample(c(1:8,NA),5e6,replace=TRUE)) 
dt2 = unique(dt2a) 

system.time(res_thela <- dt2[-dt2[, .I[any(!is.na(col2)) & is.na(col2)], by=col1]$V1]) 
# user system elapsed 
# 0.73 0.06 0.81 

system.time(res_psidom <- dt2[, .(col2 = if(all(is.na(col2))) NA_integer_ else na.omit(col2)), by = col1]) 
# user system elapsed 
# 2.86 0.03 2.89 

system.time(res <- dt2[!dt2[, .N, by=col1][N > 1L, !"N"][, col2 := dt2$col2[NA_integer_]], on=names(dt2)]) 
# user system elapsed 
# 0.39 0.01 0.41 

fsetequal(res, res_thela) # TRUE 
fsetequal(res, res_psidom) # TRUE 

方にはほとんど変化しました速度。 a having= argumentを使用すると、これはより速く、読みやすくなります。