![](/img/trans.png)
[英]Create (dplyr::mutate) and select (dplyr::select) new variables that paste two existing columns by means of a user-defined function
[英]dplyr create a new column with a complex user defined function of other columns
我有一個包含 40 個問題(下面有 3 個問題的代表)的大型數據框,需要計算一個新列,它是這 40 個響應的復雜 function。 由於幾乎不可能在mutate
中寫出 function ,因此我嘗試創建一個可以在mutate
中使用的 function f
df <- data.frame(Sex = c(rep("F", 5), rep("M", 5)),
Q1 = sample(0:10, 10, replace=T),
Q2 = sample(0:10, 10, replace=T),
Q3 = sample(0:10, 10, replace=T)
)
f <- function(q1, q2, q3){
y <- q1 + (q2^2) - (q3^3)
return(y)
}
現在使用mutate
創建一個新列可以正常工作。:
df %>%
mutate(newcol = f(Q1, Q2, Q3))
Sex Q1 Q2 Q3 newcol
1 F 10 6 3 19
2 F 0 9 9 -648
3 F 8 1 2 1
4 F 0 4 7 -327
5 F 6 4 1 21
6 M 8 3 3 -10
7 M 2 2 0 6
8 M 10 0 3 -17
9 M 6 9 3 60
10 M 1 7 2 42
一樣
df$newcol <- mapply(f, df$Q1, df$Q2, df$Q3)
但是,如果我在f
中包含一個簡單的if
atatement,如下所示
f <- function(q1, q2, q3){
y <- q1 + (q2^2) - (q3^3)
if(y<0){
y <- -y
}
return(y)
}
我的手上立刻就有了災難:
df %>%
+ mutate(newcol = f(Q1, Q2, Q3))
Sex Q1 Q2 Q3 newcol
1 F 10 6 3 19
2 F 0 9 9 -648
3 F 8 1 2 1
4 F 0 4 7 -327
5 F 6 4 1 21
6 M 8 3 3 -10
7 M 2 2 0 6
8 M 10 0 3 -17
9 M 6 9 3 60
10 M 1 7 2 42
Warning message:
Problem with `mutate()` input `newcol`.
i the condition has length > 1 and only the first element will be used
i Input `newcol` is `f(Q1, Q2, Q3)`.
然而,
df$newcol <- mapply(f, df$Q1, df$Q2, df$Q3)
df
Sex Q1 Q2 Q3 newcol
1 F 10 6 3 19
2 F 0 9 9 648
3 F 8 1 2 1
4 F 0 4 7 327
5 F 6 4 1 21
6 M 8 3 3 10
7 M 2 2 0 6
8 M 10 0 3 17
9 M 6 9 3 60
10 M 1 7 2 42
繼續工作。 不幸的是,我的 function 中有很多 if,並且有 40 種不同的 arguments 傳遞給 function,mapply 的輸入變得巨大。 如何使用預定義的向量將我的問題傳遞給 mapply,比如
questions <- c("df$Q1", "df$Q2", "df$Q3")
df$newcol <- mapply(f, questions)
密切相關:如何定義一個 function 和 40 arguments 而不會跑出頁面?
我完全有可能找錯了樹,如果是這樣,我應該如何解決我的問題?
提前謝謝了
托馬斯飛利浦
PS這是真正的標准
if(!is.na(df[i, "Q1_Daily_Mean"]) & df[i, "Q1_Daily_Mean"] >= THRESHOLD_MDD_GAD){
anxiety <- TRUE
}
if(!is.na(df[i, "Q2_Daily_Mean"]) & df[i, "Q2_Daily_Mean"] >= THRESHOLD_MDD_GAD){
worry <- TRUE
}
if(anxiety && worry){
anxiety_and_worry <- TRUE
}
if(!is.na(df[i, "Q3_Daily_Mean"]) & df[i, "Q3_Daily_Mean"] >= THRESHOLD_MDD_GAD ){
agitation <- TRUE
}
if(!is.na(df[i, "Q10_Daily_Mean"]) & df[i, "Q10_Daily_Mean"] >= THRESHOLD_MDD_GAD ){
anger <- TRUE
}
if(!is.na(df[i, "Q2_Weekly"]) & df[i, "Q2_Weekly"] >= THRESHOLD_MDD_GAD ){
physical_fatigue <- TRUE
}
if(!is.na(df[i, "Q5_Weekly"]) & df[i, "Q5_Weekly"] >= THRESHOLD_MDD_GAD ){
no_concentration <- TRUE
}
if(!is.na(df[i, "Q7_Weekly"]) & df[i, "Q7_Weekly"] >= THRESHOLD_MDD_GAD ){
disturbed_sleep <- TRUE
}
if(!is.na(df[i, "Q13_Weekly"]) & !is.na(df[i, "Q14_Weekly"]) &
!is.na(df[i, "Q15_Weekly"]) & !is.na(df[i, "Q16_Weekly"]) &
!is.na(df[i, "Q17_Weekly"]) &
max( df[i, "Q13_Weekly"], df[i, "Q14_Weekly"],
df[i, "Q15_Weekly"], df[i, "Q16_Weekly"],
df[i, "Q17_Weekly"] ) >= THRESHOLD_MDD_GAD){
max_function <- TRUE
}
sum_of_symptoms_7 <- anxiety + worry + agitation + anger +
physical_fatigue + no_concentration + disturbed_sleep
if (anxiety_and_worry && (sum_of_symptoms_7 >= CRITERIA_NEEDED_GAD) && max_function){
# Generalized Anxiety Disorder
df[i, GAD_DESCRIPTPR_EML] <- TRUE
}
基本上,帶有if
語句的 function 沒有向量化。 你有兩個選擇。
ifelse
或任何其他方式)並像之前一樣繼續使用mutate
。library(dplyr)
library(purrr)
df %>% mutate(newcol = f(Q1, Q2, Q3))
rowwise
或pmap
一次操作一行。 這類似於您的mapply
嘗試。df %>% mutate(newcol = pmap_dbl(list(Q1, Q2, Q3), ~f(..1, ..2, ..3)))
您收到“條件長度 > 1 且僅使用第一個元素”警告的原因是if
與向量結合使用(例如,請參見此處)。 dpylr
的mutate
將值的“整個”向量傳遞給被調用的 function,(即不是逐個元素的(行)元素)。 這就是if
語句被混淆的地方。
這解決了你的問題:
df <- data.frame(Sex = c(rep("F", 5), rep("M", 5)),
Q1 = sample(0:10, 10, replace=T),
Q2 = sample(0:10, 10, replace=T),
Q3 = sample(0:10, 10, replace=T)
)
f <- function(q1, q2, q3){
y <- q1 + (q2^2) - (q3^3)
y <- ifelse(y<0, -y, y)
return(y)
}
df %>%
mutate(newcol = f(Q1, Q2, Q3))
回報:
Sex Q1 Q2 Q3 newcol 1 F 8 6 3 17 2 F 6 0 0 6 3 F 4 5 7 314 4 F 9 5 7 309 5 F 3 5 9 701 6 M 1 10 5 24 7 M 10 5 4 29 8 M 4 0 3 23 9 M 8 4 7 319 10 M 3 6 3 12
要擴展我上面的評論:
f <- function(data, conditions) {
columnNames <- names(conditions)
for (colName in columnNames) {
qName <- enquo(colName)
data <- data %>% mutate(!!qName := eval(conditions[[colName]]))
}
data
}
df %>% f(list(bigQ1=expression(Q1 > 7), smallQ2=expression(Q2 < 2)))
給出,例如,
Sex Q1 Q2 Q3 bigQ1 smallQ2
1 F 2 9 9 FALSE FALSE
2 F 2 10 6 FALSE FALSE
3 F 9 4 9 TRUE FALSE
4 F 1 2 8 FALSE FALSE
5 F 5 10 2 FALSE FALSE
6 M 10 8 3 TRUE FALSE
7 M 4 8 0 FALSE FALSE
8 M 3 8 10 FALSE FALSE
9 M 5 2 6 FALSE FALSE
10 M 8 7 4 TRUE FALSE
傳遞 df 作為 function 的第一個參數允許管道。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.