创建一个新行,该新行与标量值之间存在一行差异

时间:2019-04-21 00:36:31

标签: r

假设我具有以下玩具模型,则数据集称为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包运行固定效果,但是我正在尝试手动实现。

3 个答案:

答案 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), ]