for 循环到 unlist(),选择向量元素并转换类 - 循环、列表、向量、选择
Posted
技术标签:
【中文标题】for 循环到 unlist(),选择向量元素并转换类 - 循环、列表、向量、选择【英文标题】:for loop to unlist(), select vector element & convert class - loops, list, vector, selection 【发布时间】:2022-01-22 08:28:39 【问题描述】:我在概括处理一些“问题数据”(列表的矢量化元素)的方法时遇到了问题。 (我不完全确定我是否准确地描述了这一点,所以请原谅我的无知)。
目标:
我正在尝试编译一个自动处理以下问题的函数,因为目的是重复运行/利用此方法。
问题:
我已经通过单位名称(传感器来自的设备)从数据库中提取了一些传感器数据,通常传感器数据以向量的形式出现(根据所需的结果 - 如下),但对于某些单位(数据收集器的配置不同)它返回一个向量列表。
向量中的元素数量与现场单元的数量有关(即如果现场有两个单元,/01 和 /02,那么向量将包含 2 个元素....等等)
我只想将与该单元相关的传感器数据保存在相关列中。
并非所有单元都以相同的方式配置,所以我只打算在确认列的类是一个列表时运行一个函数。
传感器的数量和标签每次都会不同(输入到主函数中)。
预期方法:
-
对每列执行以下检查和纠正措施
检查列类 - 检查类是否为“列表”
如果为 FALSE,则什么也不做。
如果为 TRUE,则使用“unlist_func”(子函数)对每一行执行以下操作:
检查'unit'列每一行的文本字符串的结尾并提取unit_no
取消列出当前元素,选择向量中与unit列中unit_no对应的数字
将列类修改为
可重现的问题:
以下小标题是我正在使用的示例:
unit <- c('a2b7/01', 'a2b7/02', 'a2b7/03', 'a2b7/01', 'a2b7/02', 'a2b7/03', 'a2b7/01', 'a2b7/02', 'a2b7/03')
sen1 <- list(c(1,2,3), c(4,5,6), c(7,8,9), c(10,11,12), c(13,14,15), c(16,17,18), c(19,20,21), c(22,23,24), c(25,26,27))
sen2 <- list(1, 2, 3, 4, 5, 6, 7, 8, 9)
sensor_data <- tibble(unit, sen1, sen2)
期望的结果:
unit <- c('a2b7/01', 'a2b7/02', 'a2b7/03', 'a2b7/01', 'a2b7/02', 'a2b7/03', 'a2b7/01', 'a2b7/02', 'a2b7/03')
sen1 <- c(1,5,9,10,14,19,23,27)
sen2 <- c(1, 2, 3, 4, 5, 6, 7, 8, 9)
sensor_data_new <- tibble(unit, sen1, sen2)
到目前为止的尝试和请求:
为了避免空手而归,我已经发布了我预期方法的草率版本,但我很抱歉,这是一项正在进行的工作,我感谢其中存在错误,但我希望能吸引那些在那里的人尽可能提供帮助或建议不同的方法。
所有建议将不胜感激。
function(unit, sensors, date_from, date_to)
# ------ QUERYING TASK ------------------------
sensor_data <- 'pulls sensor info from unit names'
# ------ SUB FUNCTION - Unlist function -------
unlist_func <- function(df = sensor_data, j)
sensor_data_distinct <- df %>%
mutate(unit_no = str_extract(unit, '\\d$')) %>%
select(unit_no) %>%
distinct()
for (i in 1:nrow(df))
if(length(df[, j[[i]] ]) => 1 & str_ends(df$unit, sensor_data_distinct$unit_no))
unlist(df[i, j])
df[sensor_data_distinct$unit_no]
else(sensor_data[, j])
# ------- STAGE 1 CLEANSING FUNCTION -------------
# unit will always be in column 1 and datetime always in column 2
stg1_cleanse <- for(j in 3:ncol(sensor_data)) # for-loop over columns
if (is.list(sensor_data[, j]) == TRUE)
lapply(unlist_func.....)
# ------- STAGE 1 CLEANSING FUNCTION -------------
stg2_cleanse <- 'further cleansing routine'
【问题讨论】:
【参考方案1】:我认为您可以大大简化您的功能。这似乎会产生您想要的结果。自定义函数extract_func
实现了检查每行长度的规则。如果是单元素值,则返回单元素;如果它是向量,则返回请求索引处的元素。然后我们可以使用 dplyr 的 rowwise
和 across
函数将此函数应用于列“sen1”和“sen2”,传递“unit_num”作为索引参数(在需要时)。
library(tidyverse)
unit <- c('a2b7/01', 'a2b7/02', 'a2b7/03', 'a2b7/01', 'a2b7/02', 'a2b7/03', 'a2b7/01', 'a2b7/02', 'a2b7/03')
sen1 <- list(c(1,2,3), c(4,5,6), c(7,8,9), c(10,11,12), c(13,14,15), c(16,17,18), c(19,20,21), c(22,23,24), c(25,26,27))
sen2 <- list(1, 2, 3, 4, 5, 6, 7, 8, 9)
sensor_data <- tibble(unit, sen1, sen2)
extract_func <- function(data, idx)
# check for NULL data and convert to NA if it is present
if (is.null(data))
data <- NA
if (length(data) == 1)
return(data[1])
else
return(data[idx])
sensor_data_clean <- sensor_data %>%
rowwise() %>%
mutate(
unit_num = as.numeric(str_extract(unit, '\\d$')),
across(c(sen1, sen2), ~extract_func(., unit_num), .names = 'extract_.col')
)
# A tibble: 9 × 6
# Rowwise:
unit sen1 sen2 unit_num extract_sen1 extract_sen2
<chr> <list> <list> <dbl> <dbl> <dbl>
1 a2b7/01 <dbl [3]> <dbl [1]> 1 1 1
2 a2b7/02 <dbl [3]> <dbl [1]> 2 5 2
3 a2b7/03 <dbl [3]> <dbl [1]> 3 9 3
4 a2b7/01 <dbl [3]> <dbl [1]> 1 10 4
5 a2b7/02 <dbl [3]> <dbl [1]> 2 14 5
6 a2b7/03 <dbl [3]> <dbl [1]> 3 18 6
7 a2b7/01 <dbl [3]> <dbl [1]> 1 19 7
8 a2b7/02 <dbl [3]> <dbl [1]> 2 23 8
9 a2b7/03 <dbl [3]> <dbl [1]> 3 27 9
由于您只是检查向量的长度然后提取单个元素,因此您可以在 mutate
内执行以下内联操作(尽管像上面这样的预定义自定义函数为您未来提供了更多的灵活性) .
sensor_data_clean <- sensor_data %>%
rowwise() %>%
mutate(
unit_num = as.numeric(str_extract(unit, '\\d$')),
across(c(sen1, sen2), ~(.[min(length(.), unit_num)]), .names = 'extract_.col')
)
【讨论】:
谢谢你,看来我把问题复杂化了。就 cross() 方面而言,我希望能够将其应用于“列表”类的任何 cloumn。我可以只使用cross(.cols = is.list(), ....... 吗?或者使用cross(.cols = Everything()....如果它正在寻找大于1的长度跨度>across(.cols = where(is.list), ... )
可能是你想要的。
啊,是的,完美。非常感谢您
嗨,如果可以的话,只是为了扩展这个问题:) 如果列表的向量元素之一中存在 NULL 值,则似乎存在问题,呈现这一点。为了处理这些 NULL 值,我打算使用线性插值函数,但我需要首先解决提取单个值的问题。我可以删除 NULL 但理想情况下我不想这样做。如果您有任何建议,将再次受到欢迎?
ie...sen1
以上是关于for 循环到 unlist(),选择向量元素并转换类 - 循环、列表、向量、选择的主要内容,如果未能解决你的问题,请参考以下文章