r - 在 R 中创建带有两个 FOR cicle 的表不会正确填充数据框“Maux”
问题描述
当我尝试从包含大量数据(totalSurvey
)的表中创建数据框时,使用这两个 for 循环(x
用于 Gender 和y
for Age)进行过滤,当循环完成时,它只有 Men 和 Age 16 的数据。什么我做错了吗?
for (x in 1:2) {
for (y in 1:4){
vGen <-ifelse(x==1, "Hombre" , ifelse(x==2, "Mujer"))
vEdad <-ifelse(y==1, "13" , ifelse( y==2, "14", ifelse( y==3, "15", "16")))
Maux <- filter(totalSurv, Genero == vGen, Edad == vEdad)
}
}
解决方案
我建议一种不同的方法。我猜缺少样本数据:
eg <- expand.grid(Genero = c("Hombre", "Mujer"), Edad = as.character(13:16))
eg$Maux <- seq_len(nrow(eg))
eg
# Genero Edad Maux
# 1 Hombre 13 1
# 2 Mujer 13 2
# 3 Hombre 14 3
# 4 Mujer 14 4
# 5 Hombre 15 5
# 6 Mujer 15 6
# 7 Hombre 16 7
# 8 Mujer 16 8
从这里,合并/加入它:
left_join(eg, totalSurv, by = c("Genero", "Edad"))
你应该有一个框架(tbl_df
),里面只有你需要的数据。这里的Maux
字段是一个整数,表示该行eg
的数据属于起始帧中的哪一行。
一种效率低得多但对您来说可能更具可读性的替代方案:
lst_of_frames <- bind_rows(lapply(1:2, function(x) {
bind_rows(lapply(1:4, function(y) {
vGen <-ifelse(x==1, "Hombre" , ifelse(x==2, "Mujer"))
vEdad <-ifelse(y==1, "13" , ifelse( y==2, "14", ifelse( y==3, "15", "16")))
filter(totalSurv, Genero == vGen, Edad == vEdad)
}))
}))
我所做的只是用调用替换你的for
循环,将它们中的每一个都包装在 a 中,并将你的和代码转储到内部循环中。lapply
dplyr::bind_rows
ifelse
filter
另一种方法是从 0 行帧开始并将rbind
每个结果附加(在 R 中)到空帧。我会提前说,这种方法是个坏主意:
Maux <- totalSurv[0,] # intentionally empty, but with all columns/classes
for (x in 1:2) {
for (y in 1:4){
vGen <-ifelse(x==1, "Hombre" , ifelse(x==2, "Mujer"))
vEdad <-ifelse(y==1, "13" , ifelse( y==2, "14", ifelse( y==3, "15", "16")))
Maux <- bind_rows(Maux, filter(totalSurv, Genero == vGen, Edad == vEdad))
}
}
值得重复,这是一个坏主意。为什么?在 R 中迭代地添加到一个框架是低效的,因为每次你只添加一行时,它都会将框架的所有内容复制到一个新对象中。这意味着如果您Maux
有 99999 行并且您只想再添加 1 行,那么您在内存中拥有这 99999 行两次。内存占用是一回事,每次这样做都需要更多时间来复制所有这些东西。
但它仍然有效,如果你只用几行这样做几次,那么一切都很好,天也不会塌陷。但是不要把我在这里提供它作为建议它是一般的正确方法。
(顺便说一句:我仍然没有修复不正确的ifelse(x==2, "Mujer")
:应该有第三个对象。或者只是将整行替换为
ifelse(x==1, "Hombre" , "Mujer")
最后一个想法:你不需要迭代数字,如果你对这些数字做的唯一事情是ifelse
ing 它们。你可以改为
Maux <- totalSurv[0,]
for (vGen in c("Hombre", "Mujer")) {
for (vEdad in as.character(13:16)) {
Maux <- bind_rows(Maux, filter(totalSurv, Genero == vGen, Edad == vEdad))
}
}
# or
Maux <- bind_rows(lapply(c("Hombre", "Mujer"), function(vGen) {
bind_rows(lapply(as.character(13:16), function(vEdad) {
filter(totalSurv, Genero == vGen, Edad == vEdad)
}))
}))
以获得更紧凑和直接代码的体验。
(但我仍然认为我的第left_join
一种方法是最直接的,并且允许您定义您需要的非常具体的组合。我为您更新的列名更新了它,顺便说一句。)
推荐阅读
- r - 无法在 R studio 中安装 glmnet 包
- javascript - 从自定义对象列表视图上的按钮创建任务
- spring-boot - 如何在同一个 Spring Boot Maven 项目中创建 Spring Boot 瘦和胖 Jar
- rust - 是否需要使用 wasm32-wasi 目标启用 --gc-sections ?
- java - Nifi ExecuteGroovyScript 使用 TestRunner 触发 onStart
- python - Flask 应用程序上的错误 404 (GET) 请求错误
- jquery - 使用 JSON 数据按搜索词排序 [JQUERY]
- microsoft-teams - Mulesoft Microsoft 团队连接器
- python - 请求库不工作?控制台中没有任何内容
- javascript - 在 React Native 中将 API 响应数据添加到之前的 AsyncStorage 数据中