我想創建一個函式,允許我輸入具有不同列數的資料框,并創建兩個新列:
- 一個基于對所有其他人的邏輯比較,并且
- 一個基于對所有其他列和第一個新列的邏輯比較。
一個最小的例子是具有兩個變數的資料集:
V1 <- c(1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0)
V2 <- c(0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0)
Data <- data.frame(V1, V2)
我想使用如下所示的函式創建兩個新列:
my.spec.df <- function(data, variables, new.var.name){
new.df <- data
# First new column
new.df[[new.var.name]] <- 0
new.df[[new.var.name]][new.df$V1 == Lag(new.df$V1, 1) & new.df$V2 == Lag(new.df$V2, 1)] <- 1 # I want my logical comparison to be applicable to all variables listed in [[variables]], not just V1 and V2 used here as minimal example
# Second new column
new.df$Conj.Var.[[new.var.name]] <- 0 # I want this second new column to take the name "Conj.Var." the name of the first new variable, which I tried to achieve with the [[]] but it did not work (same in the next row)
new.df$Conj.Var.[[new.var.name]][new.df$V1 == 1 & new.df$V2 == 1 & new.df[[new.var.name]] == 1] <- 1 # Again, I want the logical comparison to be applicable to all variables listed [[variables]] and the first newly created column
return(new.df)
}
spec.df <- my.spec.df(Data,
variables=c("V1", "V2"),
new.var.name="NV1")
新資料框應如下所示:
print(spec.df)
V1 V2 NV1 Conj.Var.NV1
1 1 0 0 0
2 0 1 0 0
3 1 1 0 0
4 1 1 1 1
5 0 0 0 0
6 0 1 0 0
7 1 0 0 0
8 1 0 1 0
9 0 0 0 0
10 0 1 0 0
11 0 1 1 0
12 1 1 0 0
13 1 0 0 0
14 0 1 0 0
15 0 0 0 0
正如代碼中所評論的,我在三件事上掙扎:
- 將第一個新列的邏輯比較應用于列出的所有變數(不僅僅是我的最小示例中的兩個變數),因為數字可以從列出的一個變數變為多個變數,
- 根據為第一個新列引入的名稱格式化第二個新列的名稱
- 將第二個新列的邏輯比較也應用于列出的所有變數。
任何人都可以提供幫助?提前謝謝了!
uj5u.com熱心網友回復:
這是一個解決方案。
它使用輔助功能all_one_by_row來完成主要作業。以及一個臨時邏輯矩陣,用于存盤與variables列中的滯后值相等的值。
all_one_by_row <- function(data, cols) {
if(missing(cols))
as.integer(rowSums(data) == ncol(data))
else
as.integer(rowSums(data[cols]) == ncol(data[cols]))
}
my.spec.df <- function(data, variables, new.var.name){
new.df <- data
# First new column
tmp <- sapply(new.df[variables], \(x) x == Lag(x, 1))
tmp[is.na(tmp)] <- FALSE
new.df[[new.var.name]] <- all_one_by_row(tmp)
# Second new column
New.Col <- paste0("Conj.Var.", new.var.name)
Cols <- c(variables, new.var.name)
new.df[[New.Col]] <- all_one_by_row(new.df, Cols)
new.df
}
spec.df <- my.spec.df(Data,
variables=c("V1", "V2"),
new.var.name="NV1")
spec.df
# V1 V2 NV1 Conj.Var.NV1
#1 1 0 0 0
#2 0 1 0 0
#3 1 1 0 0
#4 1 1 1 1
#5 0 0 0 0
#6 0 1 0 0
#7 1 0 0 0
#8 1 0 1 0
#9 0 0 0 0
#10 0 1 0 0
#11 0 1 1 0
#12 1 1 0 0
#13 1 0 0 0
#14 0 1 0 0
#15 0 0 0 0
uj5u.com熱心網友回復:
請注意,樣本資料不足以測驗超過 2 個變數的情況。注意:我在 V2 變數的位置 13 處插入了一個 1。
V1 <- c(1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0)
V2 <- c(0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0)
V3 <- c(0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0)
Data <- data.frame(V1, V2, V3)
library(tidyverse)
library(rlang)
my.spec.df <- function(data, variables, new.var.name){
x <- sym(variables[1])
y <- syms(variables[-1]) # list of variable names
ind <- ncol(data) (2 length(y))
lgl <- parse_expr(paste0(lapply(y, \(x){
paste(x, "== lag(", x, ")")
}), collapse = " & "))
lgl2 <- parse_expr(paste0(lapply(y, paste, "== 1"), collapse = " & "))
comps <- expr(!!x == x_lag & !!lgl)
comps2 <- expr(!!x == 1 & !!lgl2 & .[[ind]] == 1)
data %>%
mutate(x_lag = lag(!!x, 1, default = 0)) %>%
mutate_at(vars(!!!y), funs(lag = lag(., default = 0))) %>%
mutate("{new.var.name}" := ifelse(!!comps, 1, 0)) %>%
mutate("Conj.var.{new.var.name}" := ifelse(!!comps2, 1, 0)) %>%
select(-ends_with("lag"))
}
對于 dplyr 1.0 及更高版本,我們可以使用glue包中的語法來命名新變數,:=請參閱此帖子了解其他方法。因為我們不知道變數的數量,所以我們要動態參考新列。這個堆疊溢位帖子列出了各種方法來做到這一點。
在樣本資料上測驗時,my.spec.df(Data, variables = c("V1", "V2"), new.var.name = "NV1")回傳
V1 V2 V3 NV1 Conj.var.NV1
1 1 0 0 0 0
2 0 1 0 0 0
3 1 1 0 0 0
4 1 1 1 1 1
5 0 0 1 0 0
6 0 1 1 0 0
7 1 0 0 0 0
8 1 0 0 1 0
9 0 0 0 0 0
10 0 1 0 0 0
11 0 1 1 1 0
12 1 1 1 0 0
13 1 1 1 1 1
14 0 1 0 0 0
15 0 0 0 0 0
并my.spec.df(Data, variables = c("V1", "V2", "V3"), new.var.name = "NV1")回傳
V1 V2 V3 NV1 Conj.var.NV1
1 1 0 0 0 0
2 0 1 0 0 0
3 1 1 0 0 0
4 1 1 1 0 0
5 0 0 1 0 0
6 0 1 1 0 0
7 1 0 0 0 0
8 1 0 0 1 0
9 0 0 0 0 0
10 0 1 0 0 0
11 0 1 1 0 0
12 1 1 1 0 0
13 1 1 1 1 1
14 0 1 0 0 0
15 0 0 0 0 0
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/329723.html
