我有一个非常大的数据框,其中包括整数列statestate_cyclen.每一行都是一个GameFrame,而state描述游戏在该帧所处的状态,state_cyclen被编码以指示该状态的n次出现(基本上是data.table::rleid(state)).条件为state,循环为state_cyclen我需要从其他定义数据框中导入几列.定义数据框存储有关状态的属性,它们的行顺序通知这些属性在整个游戏中循环的方式(玩家多次遇到每个游戏状态).

以下是应该保持连接的长数据的最小示例:

data <- data.frame(
  state        = c(1, 1, 2, 2, 3, 3, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, 3, 4, 4, 3, 3),
  state_cyclen = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 1, 1, 4, 4)
)

data 
#>    state state_cyclen
#> 1      1            1
#> 2      1            1
#> 3      2            1
#> 4      2            1
#> 5      3            1
#> 6      3            1
#> 7      1            2
#> 8      1            2
#> 9      2            2
#> 10     2            2
#> 11     3            2
#> 12     3            2
#> 13     2            3
#> 14     2            3
#> 15     3            3
#> 16     3            3
#> 17     3            3
#> 18     4            1
#> 19     4            1
#> 20     3            4
#> 21     3            4

存储排序的定义数据帧的最小示例:

def_one <- data.frame(
  prop = letters[1:3],
  others = LETTERS[1:3]
)  

def_two <- data.frame(
  prop = letters[4:10],
  others = LETTERS[4:10]
) 

def_three <- data.frame(
  prop = letters[11:12],
  others = LETTERS[11:12]
) 

我有一个用基数R编写的解决方案,它可以提供所需的输出,但它的可读性不是很好,也可能不是很高效.

# Add empty columns
data$prop <- NA
data$others <- NA

# Function that recycles numeric vector bounded by a upper limit 
bounded_vec_recyc <- function(vec, n) if(n == 1) vec else (vec - 1) %% n + 1

# My solution
vec_pos_one <- data[data[, "state"] == 1, ]$state_cyclen 
vec_pos_one <- bounded_vec_recyc(vec_pos_one, n = nrow(def_one))
data[data[, "state"] == 1, ][, c("prop", "others")] <- def_one[vec_pos_one,]
  

vec_pos_two <- data[data[, "state"] == 2, ]$state_cyclen 
vec_pos_two <- bounded_vec_recyc(vec_pos_two, n = nrow(def_two))
data[data[, "state"] == 2, ][, c("prop", "others")] <- def_two[vec_pos_two,]


vec_pos_three <- data[data[, "state"] == 3, ]$state_cyclen 
vec_pos_three <- bounded_vec_recyc(vec_pos_three, n = nrow(def_three))
data[data[, "state"] == 3, ][, c("prop", "others")] <- def_three[vec_pos_three,]

data
#>    state state_cyclen prop others
#> 1      1            1    a      A
#> 2      1            1    a      A
#> 3      2            1    d      D
#> 4      2            1    d      D
#> 5      3            1    k      K
#> 6      3            1    k      K
#> 7      1            2    b      B
#> 8      1            2    b      B
#> 9      2            2    e      E
#> 10     2            2    e      E
#> 11     3            2    l      L
#> 12     3            2    l      L
#> 13     2            3    f      F
#> 14     2            3    f      F
#> 15     3            3    k      K
#> 16     3            3    k      K
#> 17     3            3    k      K
#> 18     4            1 <NA>   <NA>
#> 19     4            1 <NA>   <NA>
#> 20     3            4    l      L
#> 21     3            4    l      L

创建于2022-08-30,共reprex v2.0.2

TLDR:如你所见,我基本上是试图将这些定义数据框一个接一个地合并到对应state上的主数据框中,方法是循环使用定义数据框的行,同时保持它们的顺序,使用state_cyclen列在整个游戏中跟踪每个状态的发生情况.

有没有一种方法可以在tidyversedata.table范围内做到这一点,更快,或者至少更容易阅读?我需要这是相当快的,因为我有许多这样的GameFrame文件(在数百),他们是长的(数十万行).

附注:我不确定标题是否适合我正在进行的操作,因为我可以想象多种实现方式.欢迎对其进行编辑.

推荐答案

以下是data.table%的解决方案.我不确定它是否更容易阅读,但我很确定它更高效:

library(data.table)

dt <- rbind(setDT(def_one)[,state := 1],
            setDT(def_two)[,state := 2],
            setDT(def_three)[,state := 3])
dt[,state_cyclen := 1:.N,by = state]

data <- setDT(data)
data[dt[,.N,by = state],
     state_cyclen := bounded_vec_recyc(state_cyclen,i.N),
     on = "state",
     by = .EACHI]

dt[data,on = c("state","state_cyclen")]
    prop others state state_cyclen
 1:    a      A     1            1
 2:    a      A     1            1
 3:    d      D     2            1
 4:    d      D     2            1
 5:    k      K     3            1
 6:    k      K     3            1
 7:    b      B     1            2
 8:    b      B     1            2
 9:    e      E     2            2
10:    e      E     2            2
11:    l      L     3            2
12:    l      L     3            2
13:    f      F     2            3
14:    f      F     2            3
15:    k      K     3            1
16:    k      K     3            1
17:    k      K     3            1
18: <NA>   <NA>     4            1
19: <NA>   <NA>     4            1
20:    l      L     3            2
21:    l      L     3            2
    prop others state state_cyclen

循序渐进: 我绑定了def_one、def_Two和def_Three数据帧来创建一个data.table,其中包含需要合并的变量

dt <- rbind(setDT(def_one)[,state := 1],
            setDT(def_two)[,state := 2],
            setDT(def_three)[,state := 3])
dt[,state_cyclen := 1:.N,by = state]

如果您想要合并大量的数据帧,可以使用rbindlist和一组data.table.

然后我修改你的state_cyclenIn数据,进行与你相同的回收:

dt[,.N,by = state]

   state N
1:     1 3
2:     2 7
3:     3 2

给出你用来定义回收的长度.

data[dt[,.N,by = state],
     state_cyclen := bounded_vec_recyc(state_cyclen,i.N),
     on = "state",
     by = .EACHI]

在合并过程中,我使用by = .EACHI修改每个组的变量,使用dt[,.N,by = state]中的N变量

然后我只需执行左连接:

dt[data,on = c("state","state_cyclen")]

R相关问答推荐

R中具有gggplot 2的Likert图,具有不同的排名水平和显示百分比

名称输出pmap on tible

带有叠加饼图系列的Highmap

任意列的欧几里得距离

是否可以创建一个ggplot与整洁判断的交互作用

制作等距离的线串副本

在另存为PNG之前隐藏htmlwidget绘图元素

如何在R中描绘#符号?

仅在Facet_WRAP()中的相应方面包含geom_abline()

您是否可以使用facet_rap设置一个较低的限制来对ggmap上的比例中断进行zoom ?

R中有约束的优化问题:如何用复数和对数效益函数解决问题?

从R中的对数正态分布生成随机数的正确方法

列名具有特殊字符时的循环回归

根据纬度和距离连接两个数据集

如何在R中使用hmm TMB提前一步预测观察到的状态?

如何阻止围堵地理密度图?

减少雨云面之间的间距并绘制所有统计数据点

是否有可能从边界中找到一个点值?

把代码写成dplyr中的group_by/摘要更简洁吗?

如何在不使用SHINY的情况下将下拉滤镜列表添加到ggploy?