使用 tidyverse;在组内计算值变化之后和之前的值,为每个唯一的转变生成新变量

2023-11-23

我正在寻找一个整洁宇宙-解决方案可以计算唯一值的出现次数TF在团体内,id在数据数据中tbl. When TF我想从那一点开始向前和向后计算变化。这个计数应该存储在一个新变量中PM##, 以便PM##每个独特的转变都包含正负TF.

这个问题类似于我之前问过的一个问题,但我在这里具体来说寻找解决方案使用tidyverse tools. Uwe为最初的问题提供了一个优雅的答案data.table here.

如果这个问题违反了任何 SO 政策,请告诉我,我很乐意重新打开我的最初问题或将其附加为赏金问题。

为了说明我的问题最小工作示例。我有这样的数据,

# install.packages(c("tidyverse"), dependencies = TRUE)
library(tibble)

tbl <- tibble(id = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
                     1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7), 
              TF = c(NA, 0, NA, 0, 0, 1, 1, 1, NA, 0, 0, NA, 0, 0,
                     0, 1, 1, 1, NA, NA, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1))
tbl
#> # A tibble: 30 x 2
#>       id    TF
#>    <dbl> <dbl>
#>  1     0    NA
#>  2     0     0
#>  3     0    NA
#>  4     0     0
#>  5     0     0
#>  6     0     1
#>  7     0     1
#>  8     0     1
#>  9     0    NA
#> 10     0     0
#> # ... with 20 more rows

这就是我想要获得的,

dfa <- tibble(id = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
                     1, 1, 1, 1, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7),
              TF = c(NA, 0, NA, 0, 0, 1, 1, 1, NA, 0, 0, NA, 0, 0,
                     0, 1, 1, 1, NA, NA, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1),
              PM01 = c(NA, -3, NA, -2, -1, 1, 2, 3, NA, NA, NA, NA, -3, -2, -1,
                       1, 2, 3, NA, NA, -2, -1, 1, NA, NA, NA, NA, NA, NA, NA),
              PM02 = c(NA, NA, NA, NA, NA, -3, -2, -1, NA, 1, 2, NA, NA, NA, NA,
                       NA, NA, NA, NA, NA, NA, NA, -1, 1, 2, NA, NA, NA, NA, NA),
              PM03 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
                       NA, NA, NA, NA, NA, NA, NA, NA, -2, -1, 1, NA, NA, NA, NA),
              PM04 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
                       NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -1, 1, NA, NA, NA),
              PM05 = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
                       NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, -1, 1, 2, 3)
               )

dfa
#> # A tibble: 30 x 7
#>       id    TF  PM01  PM02  PM03  PM04  PM05
#>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1     0    NA    NA    NA    NA    NA    NA
#>  2     0     0    -3    NA    NA    NA    NA
#>  3     0    NA    NA    NA    NA    NA    NA
#>  4     0     0    -2    NA    NA    NA    NA
#>  5     0     0    -1    NA    NA    NA    NA
#>  6     0     1     1    -3    NA    NA    NA
#>  7     0     1     2    -2    NA    NA    NA
#>  8     0     1     3    -1    NA    NA    NA
#>  9     0    NA    NA    NA    NA    NA    NA
#> 10     0     0    NA     1    NA    NA    NA
#> # ... with 20 more rows

这是另一个整洁宇宙使用的方法dplyr, tidyr and zoo(用于其na.locf功能)包:

首先,而不是丢弃NAs in the TF列,然后像所有其他建议的方法一样加入回来(包括data.table方法),我在这里写了一个辅助方法,它按块向前计数,忽略NAs;

forward_count <- function(v) {
    valid <- !is.na(v)
    valid_v <- v[valid]
    chunk_size = head(rle(valid_v)$lengths, -1)
    idx <- cumsum(chunk_size) + 1
    ones <- rep(1, length(valid_v))
    ones[idx] <- 1 - chunk_size
    v[valid] <- cumsum(ones)
    v
}

它按要求工作更改后计数:

v <- sample(c(NA, 0, 1), 15, replace = T)
v
# [1] NA NA NA  0  1 NA  1 NA  1  1  0  1  0  0  0
forward_count(v)
# [1] NA NA NA  1  1 NA  2 NA  3  4  1  1  1  2  3

变更前的计数可以通过使用完全相同的函数反转向量两次来实现:

-rev(forward_count(rev(v)))
# [1] NA NA NA -1 -4 NA -3 NA -2 -1 -1 -1 -3 -2 -1

现在定义标题,向前计数列为fd,将向后列计数为bd using dplyr包裹:

library(dplyr); library(tidyr); library(zoo);

tidy_method <- function(df) {
    df %>% 
        group_by(id) %>% 
        mutate(
            rle_id = cumsum(diff(na.locf(c(0, TF))) != 0),   # chunk id for constant TF
            PM_fd = if_else(                 # PM count after change headers
                rle_id == head(rle_id, 1), 
                "head", sprintf('PM%02d', rle_id)
            ), 
            PM_bd = if_else(                 # shift the header up as before change headers
                rle_id == tail(rle_id, 1), 
                "tail", sprintf('PM%02d', rle_id+1)
            ), 
            fd = forward_count(TF),             # after change count
            bd = -rev(forward_count(rev(TF))),  # before change count
            rn = seq_along(id)) %>%             # row number
        gather(key, value, PM_fd, PM_bd) %>%    # align headers with the count
        mutate(count_ = if_else(key == "PM_fd", fd, bd)) %>%
        select(-key) %>% spread(value, count_) %>%    # reshaper PM column as headers
        select(id, TF, rn, matches('PM')) %>%  # drop no longer needed columns
        arrange(id, rn) %>% select(-rn)
}

Timingdata.table method:

定义data.table方法为:

dt_method <- function(df) {
    tmp_dt <- setDT(df)[, rn := .I][!is.na(TF)][, rl := rleid(TF), by = id][
        , c("up", "dn") := .(seq_len(.N), -rev(seq_len(.N))), by = .(id, rl)][]

    res_dt <- tmp_dt[tmp_dt[, seq_len(max(rl) - 1L), by = .(id)], on = .(id), allow.cartesian = TRUE][
        rl == V1, PM := dn][rl == V1 + 1L, PM := up][
            , dcast(.SD, id + TF + rn ~ sprintf("PM%02d", V1), value.var = "PM")][
                df, on = .(rn, id, TF)][, -"rn"]
    res_dt
}

Data:中等大小的数据,通过重复样本数据帧 200 次:

df_test <- bind_rows(rep(list(df), 200))

microbenchmark::microbenchmark(dt_method(df_test), tidy_method(df_test), times = 10)
#Unit: milliseconds
#                 expr       min        lq      mean    median        uq       max neval
#   dt_method(df_test) 2321.5852 2439.8393 2490.8583 2456.1118 2557.4423 2834.2399    10
# tidy_method(df_test)  402.3624  412.2838  437.0801  414.5655  418.6564  540.9667    10

对 data.table 方法结果进行排序id并将所有列数据类型转换为数字;结果来自data.table方法和tidyverse是相同的:

identical(
    as.data.frame(dt_method(df_test)[order(id), lapply(.SD, as.numeric)]), 
    as.data.frame(tidy_method(df_test))
)
# [1] TRUE
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 tidyverse;在组内计算值变化之后和之前的值,为每个唯一的转变生成新变量 的相关文章

  • 计算级别内的值

    我在 R 中生成了一组级别cut 例如假设 0 到 1 之间的小数值 分为 0 1 个区间 gt frac lt cut c 0 1 breaks 10 gt levels frac 1 0 001 0 1 0 1 0 2 0 2 0 3
  • R - 根据另一个数据框查找每组的重叠日期

    我有一个数据框 其中包含多个雨量计的降雨测量值 如下例所示 gt rnfl ID date value 1 250 2000 03 01 5 37 2 250 2000 03 02 0 00 3 250 2000 03 03 2 94 4
  • 有效地将环境从内部功能转移到全局环境

    我有一个在其中创建环境的函数 我希望将该环境分配给全局环境 目前我通过将环境分配给来做到这一点globalenv 作为最后一步 如下 funfun lt function inc 1 dataEnv lt new env dataEnv d
  • glm() 模型的交叉验证

    我正在尝试对我之前在 R 中构建的一些 glm 模型进行 10 倍交叉验证 我对cv glm 函数在boot包 尽管我已经阅读了很多帮助文件 当我提供以下公式时 library boot cv glm data glmfit K 10 这里
  • udunits2 R 安装:找不到 udunits2.h

    我正在尝试在 R 中安装 udunits2 以满足对ggforce包裹 但是 安装程序在检查 udunits2 时始终失败 我已经尝试过中的说明this https stackoverflow com questions 47059517
  • 通过 RSelenium 单击按钮

    我正在尝试使用 Rselarium 和 Rvest 来抓取 REI 的评论 吊床 我想点击底部的按钮 x 次 这样我就可以抓取所有评论 我有点失落 这是我到目前为止所拥有的 如果您也知道如何在取景器中预览您正在做的事情 而不是屏幕打印 那就
  • R 条形图中的 X 轴

    我想问一个关于 barplot 轴的问题 首先请看我的数据 SerNo DOY Rain 1 350 0 2 351 0 3 352 0 4 353 0 5 354 0 6 355 0 7 356 0 8 357 0 9 358 0 10
  • 如何用日语创建 ggplot2 标题?

    我正在准备日语演示文稿 并希望图像的标题和图例名称为日语 我可以让文本在 RStudio 中渲染得很好 但是当渲染图像时 日语字符仅显示为方框 x 10 10 y x x df data frame x y ggplot df aes x
  • 如何在R中逐行写入文件

    我正在尝试逐行读取 csv 文件 并且仅选择左侧的第二个和第三个单元格以及右侧的第三个单元格 例如 如果这一行中有 17 个单元格 我将选取第 15 个单元格 然后我想合并这 3 个单元格 用逗号分隔 然后将此行写入一个新的 csv 文件
  • 在ggplot2中创建部分虚线

    我正在 R 中创建一个图 并且需要创建一条线 其中某些值是投影 投影用虚线表示 这是代码 df data frame date c rep 2008 2013 by 1 value c 303 407 538 696 881 1094 gg
  • 在捕食者-被捕食者系统的生态建模中正确使用 deSolve

    我有一个捕食者 被捕食者模型 其中包含指定的参数和初始值 我在这里用两种方法求解微分方程 1 使用 for 循环 2 使用 deSolve 包 我相信 for 循环是正确的 并且应该给出如下图所示的输出 For loop attempt r
  • 如何在 Shiny 中动态渲染的 textInput 添加样式元素

    你好堆栈溢出 在我最近提出的问题中 我已经解决了一些与动态渲染 UI 元素相关的主要问题 并在一些了不起的人的帮助下动态创建了观察者 参见此处 动态渲染的 UI 如何在第二次运行时删除旧的反应变量 https stackoverflow c
  • 分割单个 SpatialPolygons 对象的多边形部分

    在 R 中 我有一个SpatialPolygons包含数百个多边形的对象 即多个多边形 我想分割这个SpatialPolygons对象放入列表中Polygons 即孔应保持连接到父多边形 知道如何做到这一点吗 EDITED 使用以下提供的示
  • 使用 R 中的 tidyverse 重新调整因子和重新排序因子

    我想使用这些功能重新调平 and 重新排序 在我的数据框中 我了解重新调整级别的工作原理 但我不明白为什么我在 data frame 中看不到级别的变化 例如 假设我有鸢尾花数据集 library tidyverse head iris g
  • 在 Linux 下更改 RStudio 用户界面(不是图形等)中的字体大小

    This is not关于更改使用 RStudio 生成的图表中的字体大小的问题 我已经知道该怎么做了 我在配备 视网膜 显示屏的 MacBook Pro 上的 Linux 下使用 RStudio 我使用 KDE 作为我的窗口管理器 我可以
  • 根据共同值对两个数据帧求和

    我有一个看起来像的数据框 day of week count 1 0 3 2 3 1 3 4 1 4 5 1 5 6 3 另一个喜欢 day of week count 1 0 17 2 1 6 3 2 1 4 3 1 5 4 5 6 5
  • 在 R Shiny 中显示/隐藏整个框元素

    我目前正在尝试找到一种方法来隐藏 显示 R Shiny 中的整个 box 元素 以及里面的所有内容 我想创建一个可能的按钮 它允许用户展开特定框 然后使用相同 甚至不同 的按钮隐藏它 我不想使用条件面板 因为我的应用程序非常大并且会产生一些
  • 使用 dplyr 的 select 引用变量名[重复]

    这个问题在这里已经有答案了 通常我会想要选择变量的子集 其中该子集是函数的结果 在这个简单的例子中 我首先获取与宽度特征相关的所有变量名称 library dplyr library magrittr data iris width var
  • R 在安装包依赖项时不考虑最大版本

    假设我正在开发一个名为magicr做一些统计魔术 我希望它使用另一个名为的包中的函数fairydust 假设 存在于 CRAN 上 很遗憾fairydust刚刚向 CRAN 发布了 2 0 0 版本 完全破坏了我计划使用的功能 所以我更新了
  • R - 如何为数据范围内的缺失值绘制条形图零点?

    假设我对 1 到 10 之间的整数的 200 个点有 10 个观察值 mysample sample rep seq 1 10 20 10 我想用条形图绘制它 barplot table mysample barplot https i s

随机推荐

  • HTML5 Canvas:缩放

    有没有简单的方法可以在画布 JavaScript 中放大和缩小 基本上我有一个 400x400px 的画布 我希望能够使用 mousedown 2x 放大并使用 mouseup 返回 过去两天用谷歌搜索 但到目前为止还没有运气 基于使用 d
  • 等待背景图像(css)加载完毕

    假设我们有一个图片幻灯片 这些图片的缩略图显示在带有滑块的 div 包装器中 我用 Jquery 创建的 并且每个图像都包含在 li 带有 CSS 背景集 它当然代表图像 我选择使用背景图像来进行布局 因为它们的大小和纵横比都不同 图像来自
  • 有哪些方法可以在 AngularJS 中显示“分块”响应?

    目前 我在显示从 Web 服务 Node js 服务器 localhost 3000 发送到 Node js 服务器 localhost 3001 上运行的模拟客户端的响应 块 时遇到问题 编辑 当前实现仅使用 Angular 的 http
  • 我可以从 popen() 流打开 bash 吗?

    根据 popen 的手册页 我正在打开 bin sh 有没有办法可以重载此行为以打开 bin bash shell 并与 BASH shell 脚本交互 或者我是否需要打开 pty 风格的连接才能做到这一点 如果您想在传递给的代码片段中使用
  • Android 警报对话框并设置肯定按钮

    这是用于滑块拼图的 我想在拼图完成时显示一个带有 确定 按钮的对话框 当按下 确定 按钮时 我使用Intent通过 Android 浏览器加载网站 唯一的问题是 使用当前代码 当拼图完成时 它不会加载盒子 当我使用null 它没有任何作用
  • 如何将 istream 与字符串一起使用

    我想将文件读入字符串 我正在寻找不同的方法来有效地做到这一点 使用固定大小的 char 缓冲区 我收到了answer来自 Tony 的内容创建了一个 16 kb 缓冲区并读取该缓冲区并追加该缓冲区 直到没有更多内容可读取 我了解它是如何工作
  • 在 XSLT 中使用 fn:sum 以及包含空值的节点集

    我正在尝试使用 XSLT 和 XPath 函数 fn sum 对 XML 中的一组值求和 只要值非空 这种方法就可以正常工作 但事实并非如此 为了说明我的问题 我举了一个例子
  • 使用 ReactiveX for Java 进行 Http 调用

    我是 ReactiveX for Java 的新手 我有以下代码块可以进行外部 http 调用 但它不是异步的 我们使用 rxjava 1 2 和 Java 1 8 private ResponseEntity
  • 如何使用 jQuery 自动跳到下一个字段?

    在 jQuery 中 如何触发用户切换到下一个输入字段的行为 我试过这个 var e jQuery Event keydown e which 9 Key code for the Tab key input trigger e 但触发事件
  • Visual Studio 2022 Xamarin Android SDK 安装模拟器“操作失败:安装 Android Emulatorv31.2.10”

    我目前正在尝试通过 Android SDK 和工具对话框安装 Android 模拟器 但我收到错误消息 操作失败 安装 Android Emulatorv31 2 10 指定的参数超出了有效值的范围 我到目前为止删除了所有设置的设备仍然没有
  • 从命令行运行 jar 时出现 MessageBodyProviderNotFoundException

    我正在使用 Java Jersey 框架 带有 Maven 并使用 IntelliJ 作为我的 IDE 我遇到过这个运行时异常 仅当我尝试从命令行运行代码时才会发生 使用 maven 进行编译 然后使用 java jar 但在 Intell
  • Xcode 9 - 无法为应用程序包 ID 创建 IXPlaceholder

    更新到 Xcode 9 并在模拟器上编译的 启动 阶段时 我收到错误 无法为应用程序包 ID 创建 IXPlaceholder 重点强调此问题仅在尝试启动模拟器时发生 因为我的实际 iPhone 6s 启动时没有任何问题 尝试 确保 inf
  • 如何在 PLAYWRIGHT 上使用选择器进行条件语句? [复制]

    这个问题在这里已经有答案了 我需要一些帮助来使用剧作家测试做出条件语句 我有一个给定的选择器 比如说一个按钮 我需要编写如下的条件语句 if selector is not present visible do nothing and pr
  • 无法在 OSX 上使用 RVM 运行 Ruby 2.2.3

    我有两台 MacBook 一台在 Mavericks 上 另一台在 Yosemite 上 并且两台 MacBook 上都会发生同样的情况 使用 RVM 安装 Ruby 2 2 3 后 出现以下错误 rvm rubies ruby 2 2 3
  • Cakephp 3 带有语言参数的路由

    我正在尝试将 cakephp 2 x 转换为 3 x 我正在使用Router connect 规则 但我尝试将它们转换为范围版本 关于 myold 路由规则 在config routes php我添加了这个 Router defaultRo
  • 测试选择器是否与给定元素匹配

    有什么方法可以测试选择器是否匹配给定的 DOM 元素 最好不使用 Sizzle 等外部库 这是针对一个库的 我想最大限度地减少 核心 库所需的第三方插件的数量 如果它最终需要 Sizzle 我会将其作为插件添加到库中 以供那些想要它启用该功
  • 角度 2 中的材料组件波斯日期选择器

    Angular2 Material 组件有一个 DatePicker 它以默认格式显示日期 并且仅支持将本地更改为 fa IR 如何格式化它以显示波斯日期 以下步骤应该有所帮助 1 在 module ts 中加载所有需要的模块 import
  • 同一级别的多个元素上的框阴影但没有重叠?

    I want to create something like the following screenshot but I can t figure out any z index value for which the shadow d
  • Eclipse:OSGI 首选项与 PreferenceStore

    我正在开发一个 Eclipse 插件 或者实际上是基于 Eclipse 的应用程序的插件 它需要用户输入一些配置 从文档来看 似乎有两种首选 API 一种是org eclipse core runtime preferences 扩展 实施
  • 使用 tidyverse;在组内计算值变化之后和之前的值,为每个唯一的转变生成新变量

    我正在寻找一个整洁宇宙 解决方案可以计算唯一值的出现次数TF在团体内 id在数据数据中tbl When TF我想从那一点开始向前和向后计算变化 这个计数应该存储在一个新变量中PM 以便PM 每个独特的转变都包含正负TF 这个问题类似于我之前