簡體   English   中英

根據R中使用data.table的B列,有條件地刪除A列中匹配的行

[英]Conditionally remove rows that match in column A, based on column B in R using data.table

嘗試使用R中的data.table來修復重復數據刪除問題

列A是名稱列表,其中一些出現多次。 B列是日期列表。 我還想復制其他一些列(發生在Name on Date上的事情。)

但是,我只想查看新數據表中每個人的最多活動,每個名稱對應於最近的日期有1個條目。

示例數據

    name.last       date
 1:     Adams 2014-10-20
 2:     Adams 2014-07-07
 3:   Barnett 2014-11-06
 4:   Barnett 2014-09-22
 5:      Bell 2014-10-22
 6:      Bell 2014-07-29
 7:     Burns 2014-09-08
 8:     Burns 2014-09-03
 9:   Camacho 2014-08-12
10:   Camacho 2014-07-08
11:  Casillas 2014-10-07
12:  Casillas 2014-07-17
13:    Chavez 2014-09-23
14:    Chavez 2014-09-17
15:   Chavira 2014-07-15
16:   Chavira 2014-07-07
17:    Claren 2014-10-30
18:    Claren 2014-10-23
19:  Colleary 2014-11-11
20:  Colleary 2014-11-07

答案只返回每個名字的第一個(因為這里的行按每個第一個的最新日期排序。)但是如果我設置dt鍵setkey(dt,name.last)以便使用unique()來刪除重復項,它按鍵順序重新排序表(按名稱字母順序)。 然后使用unique(dt)返回每個名稱的第一個外觀,這不一定是最近的日期。

如果我在兩個列setkeyv(dt,c(name.last,date))設置密鑰,那么我不能使用unique()刪除重復項,因為所有鍵都是唯一的。

問題類似於此處的一篇文章: 通過為每個組選擇一行來折疊數據框 但是我不能假設要選擇的數據是第一個還是最后一個,除非你可以建議一種操作我的數據的方法來設置密鑰。

有許多這樣做的方法沒有訂購數據表(雖然是首選排序,因為duplicated是非常有效的,你也避免使用by -將獲得這一點)。

首先,您必須確保dateDate類,以便更輕松

dt[, date := as.Date(date)]

第一個簡單的方法(雖然不是最有效的)

dt[, max(date), name.last]
#     name.last         V1
#  1:     Adams 2014-10-20
#  2:   Barnett 2014-11-06
#  3:      Bell 2014-10-22
#  4:     Burns 2014-09-08
#  5:   Camacho 2014-08-12
#  6:  Casillas 2014-10-07
#  7:    Chavez 2014-09-23
#  8:   Chavira 2014-07-15
#  9:    Claren 2014-10-30
# 10:  Colleary 2014-11-11

第二個(提供的)方法與您的類似,但是使用data.tables setorder (對於data.table版本> = 1.9.4)並且應該是最有效的

setorder(dt, name.last, -date)[!duplicated(name.last)]
#     name.last       date
#  1:     Adams 2014-10-20
#  2:   Barnett 2014-11-06
#  3:      Bell 2014-10-22
#  4:     Burns 2014-09-08
#  5:   Camacho 2014-08-12
#  6:  Casillas 2014-10-07
#  7:    Chavez 2014-09-23
#  8:   Chavira 2014-07-15
#  9:    Claren 2014-10-30
# 10:  Colleary 2014-11-11

您可以使用setkey (就像您已經做過的那樣)實現相同的setkey ,並在duplicated和刪除中指定from.last = TRUE !

setkey(dt, name.last, date)[duplicated(name.last, from.last = TRUE)]

#     name.last       date
#  1:     Adams 2014-10-20
#  2:   Barnett 2014-11-06
#  3:      Bell 2014-10-22
#  4:     Burns 2014-09-08
#  5:   Camacho 2014-08-12
#  6:  Casillas 2014-10-07
#  7:    Chavez 2014-09-23
#  8:   Chavira 2014-07-15
#  9:    Claren 2014-10-30
# 10:  Colleary 2014-11-11

第三種方法是使用data.tableunique功能(也應該非常有效)

unique(setorder(dt, name.last, -date), by = "name.last")
#     name.last       date
#  1:     Adams 2014-10-20
#  2:   Barnett 2014-11-06
#  3:      Bell 2014-10-22
#  4:     Burns 2014-09-08
#  5:   Camacho 2014-08-12
#  6:  Casillas 2014-10-07
#  7:    Chavez 2014-09-23
#  8:   Chavira 2014-07-15
#  9:    Claren 2014-10-30
# 10:  Colleary 2014-11-11

最后一種方法是使用.SD 它效率最低,但在某些情況下,當您想要獲取所有列並且不能使用duplicated函數時,它很有用

setorder(dt, name.last, -date)[, .SD[1], name.last]
#     name.last       date
#  1:     Adams 2014-10-20
#  2:   Barnett 2014-11-06
#  3:      Bell 2014-10-22
#  4:     Burns 2014-09-08
#  5:   Camacho 2014-08-12
#  6:  Casillas 2014-10-07
#  7:    Chavez 2014-09-23
#  8:   Chavira 2014-07-15
#  9:    Claren 2014-10-30
# 10:  Colleary 2014-11-11

如果我理解你的問題,我認為你可以用sqldf包更干凈地做到這一點,但缺點是你必須知道sql。

install.packages("sqldf")
library("sqldf")
dt <-data.frame(read.table(header = TRUE, text = " name.last       date
1:     Adams 2014-10-20
2:     Adams 2014-07-07
3:   Barnett 2014-11-06
4:   Barnett 2014-09-22
5:      Bell 2014-10-22
6:      Bell 2014-07-29
7:     Burns 2014-09-08
8:     Burns 2014-09-03
9:   Camacho 2014-08-12
10:   Camacho 2014-07-08
11:  Casillas 2014-10-07
12:  Casillas 2014-07-17
13:    Chavez 2014-09-23
14:    Chavez 2014-09-17
15:   Chavira 2014-07-15
16:   Chavira 2014-07-07
17:    Claren 2014-10-30
18:    Claren 2014-10-23
19:  Colleary 2014-11-11
20:  Colleary 2014-11-07")
)
head(dt)
colnames(dt) <- c('names', 'date')
sqldf("select names, min(date), max(date) from dt group by names")

希望這很有幫助。

在寫這篇文章時我發現了它。 后人......

按名稱和日期對表格進行排序,以便您可以依賴於您希望在組中的第一個或最后一個日期。 例如: dt[order(names,-date)]

然后,而不是設置一個鍵並使用unique() ,只需一個簡單的:

dt[!duplicated(names)]

names是重復列。

應輸出所需的表格。 如果有更優雅/可靠的方法來做到這一點,我會有興趣聽到它們。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM