【问题标题】:Assign Quintiles for each year in Panel data在面板数据中为每一年分配五分位数
【发布时间】:2017-01-23 02:50:38
【问题描述】:

您好,我有一个包含 3 列的面板数据:FirmYearIncome

Firm <- rep(c("AAA", "BBB", "CCC", "DDD", "EEE"), each = 20)
Year <- rep(seq(1997, 2016, 1), times = 5)
Income <- rnorm(100, mean = 50, sd = 10)
df <- cbind(Firm, Year, Income)

实际数据包含超过 5000 家公司,每家公司超过 50 年。但这是一个足够好的例子。

我想分别为所有公司每年的收入分配五分位数,并将其放入名为Quint 的新列中。 例如,对于 1997 年,公司 AAA 获得收入 50,公司 BBB 获得收入 49,公司 CCC 获得收入 48,公司 DDD 获得收入 47,公司 EEE 获得收入 46。所以公司1997 年,AAA 得了 1,BBB 得了 2,CCC 得了 3,DDD 得了 4,EEE 得了 5。

我有一个自定义函数可以多年来一直执行,但不能在每一年执行:

quan <- function (x){
  y <-ifelse(x <= quantile(x, c(.2), na.rm = TRUE), 1,
        ifelse(x > quantile(x, c(.2), na.rm = TRUE) & x <= quantile(x, c(.4), na.rm = TRUE), 2,
          ifelse(x > quantile(x, c(.4), na.rm = TRUE) & x <= quantile(x, c(.6), na.rm = TRUE), 3,        
            ifelse(x > quantile(x, c(.6), na.rm = TRUE) & x <= quantile(x, c(.8), na.rm = TRUE), 4,
              ifelse(x > quantile(x, c(.8), na.rm = TRUE), 5, NA)))))
  y
}

每年如何做?谢谢。

【问题讨论】:

  • 我认为您可以使用cutquantile 作为休息时间。如果我们想每年执行一次,请使用 aggregatedata.tabledplyr 并将“年份”作为分组变量。另外,创建df &lt;- data.frame(Firm, Year, Income)aggregate(Income ~., df, quan)
  • 顺便说一句,对于每个公司、年份、组合,您只有一个观察结果。因此,如果它仅基于“年份”作为组,则 aggregate(Income ~Year, df, quan)
  • 您的代码df &lt;- cbind(Firm,Year,Income) 创建了一个字符串矩阵。这对于您想要做的事情没有用。请改用df &lt;- data.frame(Firm,Year,Income)

标签: r panel-data custom-function


【解决方案1】:

我们需要在这里使用 group by 函数之一。使用 OP 的quan 函数,在base R,我们可以做aggregate

res <- do.call(data.frame, aggregate(Income ~Year, df, quan))

另一种选择是使用cutbreaks 作为quantiles

quan2 <- function(x) as.integer(cut(x, breaks = quantile(x, 
                   c(0, .2, .4, .6, .8, 1)), include.lowest=TRUE))

res2 <- do.call(data.frame, aggregate(Income ~Year, df, quan2))
all.equal(res1, res2)
#[1] TRUE

其他替代方案包括包解决方案,例如 data.table

library(data.table)
setDT(df)[, as.list(quan(Income)), by = Year]

dplyr/tidyr

library(dplyr)
library(tidyr)
df %>%
    group_by(Year) %>% 
    summarise(Income = list(quan(Income))) %>%
    unnest %>% 
    group_by(Year) %>% 
    mutate(ind = paste0("Income", row_number())) %>% 
    spread(ind, Income)

评论/讨论

1) aggregate 的输出导致“收入”列为matrix,因此我们将其转换为具有do.call(data.frame 的正确data.frame 列。

2) 使用cbind 创建数据集将导致matrixmatrix 只能有一个class。如果有任何character 值,则整个数据集将转换为character 矩阵。因此,当列的class 不同时,最好使用data.framelist

数据

df <- data.frame(Firm, Year, Income)

【讨论】:

  • 谢谢@akrun。但它弹出错误:参数意味着不同的行数我做了一些研究,它表明因为公司的长度不一样。我该怎么做?
  • res
  • @Dylan 您是否尝试过其他解决方案。我只是在测试时查看您的示例
  • 我也试过其他两个。 setDT(df)[, as.list(quan(Income)), by = Year] 给了我一个矩阵而不是我需要的向量。 dplyr/tidyr 版本给我错误::找不到函数“unnest”
  • @Dylan 你有最新版的tidyr吗?
猜你喜欢
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-01
  • 2014-05-01
  • 2023-01-20
  • 2020-05-09
  • 1970-01-01
相关资源
最近更新 更多