假设我具有以下玩具模型,则数据集称为Answer
:
Country year Y Ex1 Ex2
A 2015 lala 5 5
A 2016 Popo 2 2
B 2015 baba 15 60
B 2016 nono 9 20
我想针对所有数字变量全面求出2016年和2015年的平均值。确定均值后,我希望在2015年和2016年都有新行,突出显示原始值和均值之间的差异。
在这种情况下,Country A: mean(Ex1) = 3.5, mean(Ex2) = 3.5
我的最终数据集应类似于:
Country year Y Ex1 Ex2 demeanEx1 demeanEx2
A 2015 lala 5 5 . .
A 2016 Popo 2 2 . .
A 2015 lala . . 1.5 1.5
A 2016 Popo . . -1.5 -1.5
B 2015 baba 15 60 . .
B 2016 nono 9 20 . .
B 2015 baba . . 3 20
B 2016 nono . . -3 -20
如果有人想知道,我正在尝试通过为变量创建行为不端的值来手动实现固定效果。我当前的数据集中有90个变量;为所有变量手动寻找方法将是一项艰巨的任务。
我尝试使用demeanlist
包下的lfe
命令,但是每次我尝试运行R时,R都会中止。
我知道可以使用plm
通过model = within
包运行固定效果,但是我正在尝试手动实现。
答案 0 :(得分:3)
我们可以使用tidyverse
来做到这一点。按“国家/地区”分组后,transmute_at
通过从其mean
中减去“ Ex”列的值来创建“ demean”列,然后将数据与原始数据绑定(bind_rows
),arrange
(按“国家”,“年”,replace
),“ NA”在“年”,“ Y”中的每个“国家”以及该列的非NA元素
library(tidyverse)
df1 %>%
group_by(Country) %>%
transmute_at(vars(starts_with("Ex")),
list(demean = ~ . - mean(.))) %>%
bind_rows(df1, .) %>%
arrange(Country, year ) %>%
group_by(Country) %>%
mutate_at(vars(year, Y), list(~ replace(., is.na(.), .[!is.na(.)])))
# A tibble: 8 x 7
# Groups: Country [2]
# Country year Y Ex1 Ex2 Ex1_demean Ex2_demean
# <chr> <int> <chr> <int> <int> <dbl> <dbl>
#1 A 2015 lala 5 5 NA NA
#2 A 2016 Popo 2 2 NA NA
#3 A 2015 lala NA NA 1.5 1.5
#4 A 2016 Popo NA NA -1.5 -1.5
#5 B 2015 baba 15 60 NA NA
#6 B 2016 nono 9 20 NA NA
#7 B 2015 baba NA NA 3 20
#8 B 2016 nono NA NA -3 -20
或以稍微修改的方式
df1 %>%
group_by(Country) %>%
nest %>%
mutate(data = map(data, ~
.x %>%
transmute_at(vars(starts_with("Ex")),
list(demean = ~ . - mean(.))) %>%
bind_cols(.x[1:2], .) %>%
bind_rows(.x, .))) %>%
unnest
df1 <- structure(list(Country = c("A", "A", "B", "B"), year = c(2015L,
2016L, 2015L, 2016L), Y = c("lala", "Popo", "baba", "nono"),
Ex1 = c(5L, 2L, 15L, 9L), Ex2 = c(5L, 2L, 60L, 20L)),
class = "data.frame", row.names = c(NA, -4L))
答案 1 :(得分:2)
一次基本的R尝试,使用ave
来获取与各自平均值的差异,并进行一些索引操作以覆盖旧值和新值的集合:
meas <- c("Ex1","Ex2")
s <- seq_len(nrow(dat))
out <- dat[rep(s,2),]
out[-s, meas] <- NA
out[-s, paste0("demean",meas)] <- lapply(
dat[meas],
function(x) x - ave(x,dat["Country"])
)
out
# Country year Y Ex1 Ex2 demeanEx1 demeanEx2
#1 A 2015 lala 5 5 NA NA
#2 A 2016 Popo 2 2 NA NA
#3 B 2015 baba 15 60 NA NA
#4 B 2016 nono 9 20 NA NA
#1.1 A 2015 lala NA NA 1.5 1.5
#2.1 A 2016 Popo NA NA -1.5 -1.5
#3.1 B 2015 baba NA NA 3.0 20.0
#4.1 B 2016 nono NA NA -3.0 -20.0
dat
所在的位置:
dat <- read.table(text="Country year Y Ex1 Ex2
A 2015 lala 5 5
A 2016 Popo 2 2
B 2015 baba 15 60
B 2016 nono 9 20", header=TRUE)
答案 2 :(得分:2)
计算并附加demean *列,然后将其rbind到其自身,从而NA出相应的列。最后重新排序。不使用任何软件包。
a <- transform(Answer, demean1 = Ex1 - ave(Ex1, Country), demean2 = Ex2 - ave(Ex2, Country))
a2 <- rbind(transform(a, demean1 = NA, demean2 = NA), transform(a, Ex1 = NA, Ex2 = NA))
a2[order(a2$Country), ]
结果是:
Country year Y Ex1 Ex2 demean1 demean2
1 A 2015 lala 5 5 NA NA
2 A 2016 Popo 2 2 NA NA
5 A 2015 lala NA NA 1.5 1.5
6 A 2016 Popo NA NA -1.5 -1.5
3 B 2015 baba 15 60 NA NA
4 B 2016 nono 9 20 NA NA
7 B 2015 baba NA NA 3.0 20.0
8 B 2016 nono NA NA -3.0 -20.0
或者,如果我们不知道有多少个Ex列,则首先将ix
定义为Ex
列的列号,然后将脱气值计算为demeans
。
创建一个三列列的数据框,如图所示。最后对它进行排序。
# ix <- 4:ncol(Answer)
ix <- grep("Ex", names(Answer)) ##
demeans <- Answer[ix] - sapply(Answer[ix], ave, Answer$Country)
names(demeans) <- paste0("demean", names(demeans))
aa <- cbind(
Answer[-ix],
rbind(Answer[ix], NA * Answer[ix]),
rbind(NA * demeans, demeans)
)
aa[order(aa$Country), ]