【发布时间】:2021-02-27 22:46:08
【问题描述】:
使用下面的数据,我想将以下操作向量化为 apply 调用,但这样做时我会丢失每个向量化操作的相关数。
示例数据如下:
library(VGAM)
library(dplyr)
df<- structure(list(id_choice = c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L,3L), V1 = c(-2.1578610393492, -7.99842015838894, -2.75141490020271,-10.4498142778112, -1.24287958770339, -0.378360296432904, -5.4054060545789,-1.91973213468639, -3.43124320737278), V2 = c(-0.707981236327309,-2.46810236795902, -0.929869936267716, -5.0157210007768, -0.602127441470801,-0.186681393158885, -2.06095189374723, -0.706069723181491, -1.04581628613078), V3 = c(-0.707981236327309, -2.46810236795902, -0.929869936267716,-3.34318115860932, -0.419902425557776, -0.141349098342894, -2.06095189374723,-0.706069723181491, -1.04581628613078)), row.names = c(NA, -9L), groups = structure(list(id_choice = 1:3, .rows = structure(list(1:3, 4:6, 7:9), ptype = integer(0), class = c("vctrs_list_of","vctrs_vctr", "list"))), row.names = c(NA, 3L), class = c("tbl_df","tbl", "data.frame"), .drop = TRUE), class = c("grouped_df","tbl_df", "tbl", "data.frame"))
# id_choice V1 V2 V3
# 1 1 -2.16 -0.708 -0.708
# 2 1 -8.00 -2.47 -2.47
# 3 1 -2.75 -0.930 -0.930
# 4 2 -10.4 -5.02 -3.34
# 5 2 -1.24 -0.602 -0.420
# 6 2 -0.378 -0.187 -0.141
# 7 3 -5.41 -2.06 -2.06
# 8 3 -1.92 -0.706 -0.706
# 9 3 -3.43 -1.05 -1.05
我需要对每个 V1、V2 和 V3 应用相同的 2 个操作。它们是:
- 生成
U <- V + Gumbel error - 生成一个二进制 (
choice) 变量,该变量在Ubyid_choice的最大值处取值 1
广泛(而且绝对不合适)的方法如下(也非常欢迎对当前方法的第 2 点进行任何改进)。我将其称为哑方法
Dumb [but working] 方法
# For V1...
# adding the random part to the error rgumbel
df$U1 <- df$V1 + rgumbel(nrow(df) , loc=0 , scale=1)
# generating choice variable
id_choice_split_1 <- with(df, split(U1,id_choice))
df$choice1 <- unlist(lapply(id_choice_split_1,
function(uValues)
as.numeric(uValues == max(uValues))))
# ...for V2...
# adding the random part to the error rgumbel
df$U2 <- df$V2 + rgumbel(nrow(df) , loc=0 , scale=1)
# generating choice variable
id_choice_split2 <- with(df, split(U2,id_choice))
df$choice2 <- unlist(lapply(id_choice_split2,
function(uValues)
as.numeric(uValues == max(uValues))))
# ...for V3.
# adding the random part to the error rgumbel
df$U3 <- df$V3 + rgumbel(nrow(df) , loc=0 , scale=1)
# generating choice variable
id_choice_split3 <- with(df, split(U3,id_choice))
df$choice3 <- unlist(lapply(id_choice_split3,
function(uValues)
as.numeric(uValues == max(uValues))))
导致……
# id_choice V1 V2 V3 U1 choice1 U2 choice2 U3 choice3
# 1 1 -2.16 -0.708 -0.708 -2.89 0 -1.09 1 -1.42 0
# 2 1 -8.00 -2.47 -2.47 -8.94 0 -3.17 0 -2.15 0
# 3 1 -2.75 -0.930 -0.930 -2.51 1 -1.22 0 -0.130 1
# 4 2 -10.4 -5.02 -3.34 -8.87 0 -5.77 0 -2.82 0
# 5 2 -1.24 -0.602 -0.420 1.30 1 -0.477 0 -0.942 0
# 6 2 -0.378 -0.187 -0.141 -0.463 0 1.49 1 -0.121 1
# 7 3 -5.41 -2.06 -2.06 -4.28 0 -0.509 0 -1.31 0
# 8 3 -1.92 -0.706 -0.706 -0.633 1 -0.486 1 1.77 1
# 9 3 -3.43 -1.05 -1.05 -2.89 0 -1.68 0 -0.975 0
最后,只保留相关变量(又名:id_choicechoice1、choice2 和 choice3)。
这是我的想要的输出
#keeping just relevant variables
df<- data.frame(select(df,-c(U1,V1,
U2,V2,
U3,V3)))
# id_choice choice1 choice2 choice3
# 1 1 0 1 0
# 2 1 0 0 0
# 3 1 1 0 1
# 4 2 0 0 0
# 5 2 1 0 0
# 6 2 0 1 1
# 7 3 0 0 0
# 8 3 1 1 1
# 9 3 0 0 0
鉴于只是重复操作,我宁愿将它们自动化。因此,我创建了一个使用apply 调用的函数:
聪明的[但还没有工作]方法
choice_generator <- function(V){
require(VGAM)
V <- as.data.frame(V)
# adding the random part to the error rgumbel
U <- V + rgumbel(nrow(V) , loc=0 , scale=1)
# generating choice variable
id_choice_split <- with(df, split(U,id_choice))
choice <- unlist(lapply(id_choice_split,
function(uValues) as.numeric(uValues == max(uValues))))
#keep it as data.frame
choice <- data.frame(choice)
}
# getting a list with the choice variables
list_with_choices <- apply(df[grep('V', names(df))] ,
MARGIN = 2,
FUN =choice_generator )
#generate_data_frame from the obtained list.
df$choices <- do.call("cbind", list_with_choices)
导致...
# id_choice V1 V2 V3 choices$choice $choice $choice
# 1 1 -2.16 -0.708 -0.708 0 0 1
# 2 1 -8.00 -2.47 -2.47 0 0 0
# 3 1 -2.75 -0.930 -0.930 1 1 0
# 4 2 -10.4 -5.02 -3.34 0 0 0
# 5 2 -1.24 -0.602 -0.420 0 0 0
# 6 2 -0.378 -0.187 -0.141 1 1 1
# 7 3 -5.41 -2.06 -2.06 0 0 0
# 8 3 -1.92 -0.706 -0.706 1 1 0
# 9 3 -3.43 -1.05 -1.05 0 0 1
#New names:
#* choices.choice -> choices.choice...5
#* choices.choice -> choices.choice...6
#* choices.choice -> choices.choice...7
colnames(df)
#[1] "id_choice" "V1" "V2" "V3" "choices"
如你所见,我失去了我想要的输出,因为我从愚蠢的方法中得到的 choice1、choice2 和 choice3 的相关数量 不见了。
可以通过修改我的函数来保留相关数字吗?还是我想念的另一件事?提前感谢您的宝贵时间!
【问题讨论】:
标签: r dataframe dplyr vectorization apply