R语言 显示二元变量永久变化的变量

2lpgd968  于 2022-12-20  发布在  其他
关注(0)|答案(1)|浏览(150)

我试图创建一个虚拟变量,它将说明另一个虚拟变量的变化,对于我的横截面时间序列面板数据,它是二分法的。
换句话说,我有一个包含3个值的变量(将其称为变量open):1 0 NA.
open表示一个国家是否正在向更开放的社会过渡,因此,变量最有可能重复它自己。我尝试编写3个不同的虚拟变量来说明open中的变化,例如:
每次open中出现正数值变化时,open1的值将为1(因此,无论open何时从NA变为1,它都无法识别),而只能从0变为1
open2将说明open1的相反情况。即,每当open0变为1时。类似地,不识别关于NA的差异。
open3需要在open0变为1的一年期间获得值1,并将该值保留至少5年。
我试图用以下数据来说明这些变量:

#    Country Year open open1 open2 open3
# 1       US    1    1     0     0     0
# 2       US    2    0     0     1     0
# 3       US    3    1     1     0     0
# 4       US    4   NA     0     0     0
# 5       US    5    0     0     0     0
# 6       US    6    0     0     0     0
# 7       UK    1   NA     0     0     0
# 8       UK    2    0     0     0     0
# 9       UK    3    1     1     0     1
# 10      UK    4    1     0     0     0
# 11      UK    5    1     0     0     0
# 12      UK    6    1     0     0     0
# 13      UK    7    1     0     0     0

数据

read.table(
  text =
    "Country, Year, open, open1, open2, open3
US, 1, 1, 0, 0, 0
US, 2, 0, 0, 1, 0
US, 3, 1, 1, 0, 0
US, 4, NA, 0, 0, 0
US, 5, 0, 0, 0, 0
US, 6, 0, 0, 0, 0 
UK, 1, NA, 0, 0, 0
UK, 2, 0, 0, 0, 0
UK, 3, 1, 1, 0, 1
UK, 4, 1, 0, 0, 0 
UK, 5, 1, 0, 0, 0
UK, 6, 1, 0, 0, 0
UK, 7, 1, 0, 0, 0", sep = ",", header = TRUE)
niwlg2el

niwlg2el1#

前两个要求很简单。
1.计算矢量open差值;
1.如果它们是正的,它们从0变到1,如果它们是负的,它们从1变到0。稍后处理NA

open1 <- as.integer(c(0L, diff(df1$open)) == 1L)
open1[is.na(open1)] <- 0L
identical(df1$open1, open1)
#> [1] TRUE

open2 <- as.integer(c(0L, diff(df1$open)) == -1L)
open2[is.na(open2)] <- 0L
identical(df1$open2, open2)
#> [1] TRUE

创建于2022年12月18日,使用reprex v2.0.2
第三个要求用游程编码技巧解决,取长度等于或大于5的1的重复,用FALSE/TRUE代替值和逆规则。

r <- rle(df1$open)
r$values <- as.integer(r$lengths >= 5 & r$values == 1L)
open3 <- c(0L, diff(inverse.rle(r)))
identical(df1$open3, open3)
#> [1] TRUE

创建于2022年12月18日,使用reprex v2.0.2

按国家

现在将上面的内容写成函数,并将每个函数应用于按国家划分的数据。
下面是一个by的解决方案。我在按原始顺序排序后测试了它(order是它自己的反函数),将原始df1与它的前3列加上代码的结果进行比较,两者是相同的。

fun1 <- function(x, d = 1L) {
  o <- as.integer(c(0L, diff(x)) == d)
  o[is.na(o)] <- 0L
  o
}

fun2 <- function(x, d = 1L, nyears = 5L) {
  r <- rle(x)
  r$values <- as.integer(r$lengths >= nyears & r$values == d)
  o <- c(0L, diff(inverse.rle(r)))
  o
}

res <- by(df1, df1$Country, FUN = \(X) {
  cbind(
    open1 = fun1(X$open, 1L),
    open2 = fun1(X$open, -1L),
    open3 = fun2(X$open)
  )
})

res <- do.call(rbind, res)
i <- order(df1$Country, df1$Year)
res <- res[order(i), ]

identical(df1, cbind(df1[1:3], res))
#> [1] TRUE

cbind(df1[1:3], res)
#>    Country Year open open1 open2 open3
#> 1       US    1    1     0     0     0
#> 2       US    2    0     0     1     0
#> 3       US    3    1     1     0     0
#> 4       US    4   NA     0     0     0
#> 5       US    5    0     0     0     0
#> 6       US    6    0     0     0     0
#> 7       UK    1   NA     0     0     0
#> 8       UK    2    0     0     0     0
#> 9       UK    3    1     1     0     1
#> 10      UK    4    1     0     0     0
#> 11      UK    5    1     0     0     0
#> 12      UK    6    1     0     0     0
#> 13      UK    7    1     0     0     0

创建于2022年12月18日,使用reprex v2.0.2

数据

我重新发布数据是因为在我的R会话中open是作为字符读取的。设置参数colClasses解决了这个问题。

df1 <- read.table(
  text =
    "Country, Year, open, open1, open2, open3
US, 1, 1, 0, 0, 0
US, 2, 0, 0, 1, 0
US, 3, 1, 1, 0, 0
US, 4, NA, 0, 0, 0
US, 5, 0, 0, 0, 0
US, 6, 0, 0, 0, 0 
UK, 1, NA, 0, 0, 0
UK, 2, 0, 0, 0, 0
UK, 3, 1, 1, 0, 1
UK, 4, 1, 0, 0, 0 
UK, 5, 1, 0, 0, 0
UK, 6, 1, 0, 0, 0
UK, 7, 1, 0, 0, 0", sep = ",", header = TRUE, 
  colClasses = c("character", rep("integer", 5)))

创建于2022年12月18日,使用reprex v2.0.2

相关问题