2017-09-01 14 views
2

Rで難しいデータ操作の問題を扱っています。現在、forループを使用して問題に近づいていますが、これをベクトル化してより良いスケール。データフレーム内の重複データを排除するfor-loopをベクトル化するR

dput(mydf) 
structure(list(team_id = c(14L, 14L, 7L, 7L, 21L, 21L, 15L, 15L 
), opp_team_id = c(7L, 7L, 14L, 14L, 15L, 15L, 21L, 21L), pg = c(3211L, 
3211L, 786L, 786L, 3914L, 644L, 1524L, 593L), sg = c(653L, 4122L, 
1512L, 1512L, 2593L, 10L, 54L, 54L), sf = c(4122L, 1742L, 2347L, 
2347L, 1352L, 3378L, 2843L, 1062L), pf = c(1742L, 886L, 79L, 
1134L, 687L, 1352L, 1376L, 1376L), c = c(3014L, 2604L, 2960L, 
2960L, 21L, 3216L, 1256L, 3017L), opp_pg = c(3982L, 3982L, 3211L, 
4005L, 1524L, 1524L, 3914L, 644L), opp_sg = c(786L, 2347L, 653L, 
653L, 54L, 802L, 2593L, 10L), opp_sf = c(1134L, 1134L, 4122L, 
1742L, 1062L, 1062L, 3105L, 3105L), opp_pf = c(183L, 183L, 1742L, 
886L, 3017L, 1376L, 3216L, 2135L), opp_c = c(2475L, 2960L, 3138L, 
3138L, 1256L, 3017L, 21L, 1957L)), .Names = c("team_id", "opp_team_id", 
"pg", "sg", "sf", "pf", "c", "opp_pg", "opp_sg", "opp_sf", "opp_pf", 
"opp_c"), row.names = c(NA, -8L), class = "data.frame") 

mydf 
    team_id opp_team_id pg sg sf pf c opp_pg opp_sg opp_sf opp_pf opp_c 
1  14   7 3211 653 4122 1742 3014 3982 786 1134 183 2475 
2  14   7 3211 4122 1742 886 2604 3982 2347 1134 183 2960 
3  7   14 786 1512 2347 79 2960 3211 653 4122 1742 3138 
4  7   14 786 1512 2347 1134 2960 4005 653 1742 886 3138 
5  21   15 3914 2593 1352 687 21 1524  54 1062 3017 1256 
6  21   15 644 10 3378 1352 3216 1524 802 1062 1376 3017 
7  15   21 1524 54 2843 1376 1256 3914 2593 3105 3216 21 
8  15   21 593 54 1062 1376 3017 644  10 3105 2135 1957 

手元にある私の問題に基づいて、行3-4と7-8はこのデータフレームに重複しています。行3-4は行1-2の複製であり、行7-8は行5-6の複製です。これはスポーツデータであり、3行目から4行目は本質的に行1と行2であり、team_idとopp_team_idが切り替えられている点を除き、他の10列(大部分は同じ)に対して同じです。ここで

私は非常に創造的であるが、それにもかかわらず、forループだと思う、重複除去のために私のためのループです:forループ

indices = c(1) 
TFSwitch = TRUE 
for(i in 2:nrow(mydf)) { 
    last_row = mydf$team_id[(i-1)] 
    this_row = mydf$team_id[i] 

    TFSwitch = ifelse(last_row != this_row, !TFSwitch, TFSwitch) 

    if(TFSwitch == TRUE) { 
    indices = c(indices, i) 
    } 
} 

これはteamID列の変更かどうかをチェックする前後に行くを行から行へ移動し、そうであれば、TFSwitchをTRUEからFALSEに、またはその逆に切り替えます。次に、保持したいインデックスをベクターに保存します。

私はこれをベクトル化したいと思います - どんな考えも大歓迎です!

答えて

4

これは、(pair-wise duplicate removal from dataframe)のようなペアごとの重複除去を含む以前の問題に非常に似ています。だから、同様の手順を以下、およびインデックスを取得するには少しmerge()バックを追加し、あなたが行うことができます:ここでは

vars <- c("team_id","opp_team_id") 

mx <- do.call(pmax, mydf[vars]) 
mn <- do.call(pmin, mydf[vars]) 

merge(
    cbind(mydf[vars], ind=seq_len(nrow(mydf))), 
    mydf[!duplicated(data.frame(mx,mn)), vars] 
)[,"ind"] 

# [1] 1 2 5 6 
+0

本当にありがとうございました。私のスクリプトでは実際にエラーが発生しました。 1つのチームIDが変更されたが、別のチームIDが変更されなかった場合、forループはそれらのインデックスを取得しませんでした。 – Canovice

1

同じ溶液をdata.tableを使用します。私の控えめなことは、ユニークなインデックスを見つけるだけでなく、ペアごとに複製を削除したいということです。

library(data.table) 
setDT(mydf) 
mydf[,c("id1","id2"):=list(pmax(team_id,opp_team_id),pmin(team_id,opp_team_id))] 
setkey(mydf,team_id,opp_team_id)[unique(mydf,by=c("id1","id2"))] 
関連する問題