[英]R Loop for matched data.table columns
我真的很難創建一個運行模型的函數,其中所有變量a
, b
, d
, g
和N
都有多個版本,如data.table中所示,在下面我將其命名為crm
:
crm = data.table(
East = 26500,
North = c(115000, 120000, 125000, 130000, 135000, 140000),
rain = c(1049.61, 1114.31, 1361.61, 1407.2, 1499.56, 1654.13),
crop = 'Wheat', area = c(0.1718, 0.1629, 0.1082, 0.0494, 0.02, 0.004),
rn = c("10007", "10018", "10023", "10024", "10025", "10026"),
N1 = 184.262648839489, N2 = 180.312874871521, N3 = 178.615847839997,
N4 = 182.531626054579, a1 = 0.186117715072018, a2 = -0.0232731908915799,
a3 = 0.227017532149122, a4 = 0.162943230565506, b1 = 0.000478900233700419,
b2 = 0.000787931973696371, b3 = 0.000458478256537521, b4 = 0.000517304324750896,
d1 = -0.000328164576390286, d2 = -0.000112122093240884, d3 = 0.000112702113716146,
d4 = 7.40875908059628e-05, g1 = 4.04709473710477e-06, g2 = 3.68724096485995e-06,
g3 = 3.47214450131546e-06, g4 = 3.55825543257538e-06, key = 'rn'
)
我想做的是運行下面的函數來計算lnN
的值,並將其放入與標題中與輸入模型的變量具有相同編號的列中。 即使用a1
, b1
, d1
, g1
和N1
將生成lnN1
列,依此類推,對於所有2s,3s和4s。
n <- 1:4
cols <- paste0("lnN",n)
for(i in 1:length(n)){
crm[,(cols) := lapply(.SD ,function (x) {
N = crm[,7+i]
a = crm[,11+i]
b = crm[,15+i]
d = crm[,19+i]
g = crm[,23+i]
a + (b*crm[,rain]) + (g*N) + (d*crm[,rain]*N)}), .SDcols = paste0("N",n)]
}
我還沒有找到有關如何完成此操作的示例。 我嘗試使用mapply
但看不到如何在每個變量的所有迭代中迭代mapply。 謝謝您的幫助!
怎么樣:
library(dplyr)
cbind(crm, do.call(cbind,
lapply(1:4, function(x) {
select(crm, c(contains(as.character(x)), rain)) %>%
setnames(gsub("[0-9]", "", names(.))) %>%
transmute(lnN = a + (b*rain) + (g*N) + (d*rain*N)) %>%
setnames(paste0("lnN", x))
})
))
主要思想是,對於每個數字,僅選擇包含該數字的列(還包括rain
),重命名這些列以刪除數字,應用公式,重命名結果列以附加該數字,然后將結果cbind
到原始表。
因此,看了上面的評論后,我發現嘗試將迭代次數更改為數千時可能會出現問題,因為Frank和Weihuang都建議我重新考慮如何構造數據。
相反,我要做的是將隨機生成的變量矩陣保留為單獨的數據框。 e
包含多元隨機值a
, b
, g
& d
與N
(現在稱為Nit
)在rnm
。 因此, crm
現在只有前六列。 代碼如下:
for(i in 1:n){
a = e[1,i]
b = e[2,i]
g = e[3,i]
d = e[4,i]
Nit = rnm[i]
bob = a + (b*crm$rain) + (g*Nit) + (d*crm$rain*Nit)
data.y <- cbind(data.y, bob)
}
crm <- cbind(crm, data.y)
names(crm)[c(7:n)] = names(bobs)
對於1:n的每次迭代,它將讀取每個參數的i
值(所有1s,所有2s等),並將其放入模型中,並創建一個名為bob
的列。 然后將bob
合並到我在函數( data.y
)之前創建的空數據框中。 這樣循環直到達到所需的循環次數。
然后,我使用cbind
將兩者合並在一起,然后使用存儲在數據框bobs
中的名稱順序重命名所有bob
列,該數據幀包含從.csv
文件讀取的列標題為bob.1
到bob.n
的列標題的列表我用Excel制作。
這里有一個melt
-和- dcast
( recast
)版本借力新實施的功能melt
的patterns
利用提供的名稱。 有關說明,請參閱安裝Wiki ,因為這是當前正在開發中的功能。
library(data.table) 1.10.5+
# create character version of 1:N (Number of output columns)
N = paste0(seq_len(length(grep('^b', names(crm)))))
# join crm to a melt & recast version of itself using rain as
# the join key (note this will fail if the amount of rain may
# not be unique -- in this case, we should include some ID in
# id.vars, like rn, and adjust accordingly)
crm = crm[crm[ , melt(.SD, id.vars = 'rain',
measure.vars = patterns(N = '^N[0-9]', a = '^a[0-9]',
b = '^b', d = '^d', g = '^g'))
# use the formula to generate ln
][ , ln := a + b*rain + g * N + d * rain * N
# reshape wide
][ , dcast(.SD, rain ~ variable, value.var = 'ln')
# rename the columns here
][ , setnames(.SD, N, paste0('ln', N))],
on = 'rain']
# by-reference version
crm[crm[ , melt(.SD, id.vars = 'rain',
measure.vars = patterns(N = '^N[0-9]', a = '^a[0-9]',
b = '^b', d = '^d', g = '^g'))
# use the formula to generate ln
][ , ln := a + b*rain + g * N + d * rain * N
# reshape wide
][ , dcast(.SD, rain ~ variable, value.var = 'ln')],
# mget tends to be sort of slow, which is why I used the
# assign-by-copy approach first above; in larger examples,
# this slow-down may be outweighed by the cost of copying
paste0('ln', N) := mget(N), on = 'rain']
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.