![](/img/trans.png)
[英]how to conditionally create new column based on the values of a column in one dataframe and the column header names of another dataframe in R
[英]Assigning 1 or 0 conditionally to a new column based on values from another dataframe in R
我有一個32,000個條目的data.frame
。 這是一個示例:
# df1
MINEVENT MAXEVENT EVENTRANGE NUMEVENT cplt_flag
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
另一個帶有157個值的列表。 這是一個示例:
# df2
source_id
211535
211535
211535
211536
211536
211536
我想從source_id
讀取並測試該值是否介於MINEVENT
和MAXEVENT
之間。 如果為TRUE
則我想在cplt_flag
輸入值1
,否則為0
。
我有一個使用if-else
語句的代碼,但對於32,000
個條目,它的運行速度非常慢。 另外,我一直在嘗試使用函數和應用函數,但是無法使其正常工作。
我正在尋找一種有效的方法來完成此任務。
您的數據集實際上並沒有任何可能會出現TRUE
情況的情況。但是,這是一個使用data.table v1.9.7當前開發版本中新的非等額聯接功能的解決方案。 請參閱此處的安裝說明。
require(data.table) #v1.9.7+
setDT(df2)
setDT(df1)[df2, cplt_flag := 1, on = .(MINEVENT <= source_id, MAXEVENT >= source_id)]
對於df2
每一行,在滿足提供給on=
參數的條件的情況下,從df1
中提取匹配的行索引。 在這些行索引上, cplt_flag
更新為1
。
使用match.criterion
函數和apply函數之一的替代解決方案,該解決方案應比循環更快。 我添加了一些額外的數據行進行測試(不是窮舉,而是說明性的):
df1 <- read.table(text = "
MINEVENT MAXEVENT EVENTRANGE NUMEVENT cplt_flag
211535 211634 211535-211634 100 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680001 2680051 2680001-2680051 51 0
2680101 2680151 2680101-2680151 51 0", header = TRUE)
df2 <- read.table(text = "
source_id
211535
211535
211535
211536
211536
211536
2680051", header = TRUE)
match.criterion <- function(source.id, df1) {
matches <- which(df1$MINEVENT <= source.id & source.id <= df1$MAXEVENT)
df1$cplt_flag[matches] <<- 1
}
sapply(df2$source_id, match.criterion, df1 = df1)
print(df1)
## MINEVENT MAXEVENT EVENTRANGE NUMEVENT cplt_flag
##1 211535 211634 211535-211634 100 1
##2 2680001 2680051 2680001-2680051 51 1
##3 2680001 2680051 2680001-2680051 51 1
##4 2680001 2680051 2680001-2680051 51 1
##5 2680001 2680051 2680001-2680051 51 1
##6 2680001 2680051 2680001-2680051 51 1
##7 2680001 2680051 2680001-2680051 51 1
##8 2680101 2680151 2680101-2680151 51 0
筆記:
這里的關鍵是了解R的作用域規則 。 要在函數范圍之外修改變量,請使用<<-
代替<-
。 請參閱此以獲取解釋,並注意有關使用<<-
的警告。
假設df1$cplt_flag
最初為全零,因為match.criterion
僅將匹配的行設置為1
。 也就是說,與source_id
每個值的標准都不匹配的df1
行將被保留。
使用foreach
而不是apply函數之一的另一個矢量化解決方案是:
require(foreach)
foreach(source.id = df2$source_id) %do% match.criterion(source.id, df1)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.