Winsorizing Panel Data (dataframe) по годам и обрезка по определенным условиям

Я пытаюсь выполнить winsorize (заменяя выбросы значениями, которые на 2 или 3 стандартных отклонения от среднего) для панельных данных и за каждый год. Я установил пакет robustHD, который включает в себя такую ​​функцию, однако я не могу реализовать ее в своем наборе данных.

Мой набор данных похож на Grunfeld (хотя у меня есть NA) с разными фирмами за те же годы. (1935-1954)

> head(Grunfeld, 6)
  firm year   inv  value capital
1    1 1935 317.6 3078.5     2.8
2    1 1936 391.8 4661.7    52.6
3    1 1937 410.6 5387.1   156.9
4    1 1938 257.7 2792.2   209.2
5    1 1939 330.8 4313.2   203.4
6    1 1940 461.2 4643.9   207.2

Что я хотел бы сделать сейчас, так это выбрать только определенные столбцы (например, inv и стоимость) по всем фирмам и сохранить их в кадре данных с той же структурой. Я попробовал следующий код:

Цель в основном состоит в том, чтобы получить винсоризированную копию исходного фрейма данных (все структурировано одинаково).

Как предложено ниже, plyr — это хороший способ разделить кадры данных и применить функции, но я не могу заставить его работать.

library(plm)
library(robustHD)
library(plyr)

data("Grunfeld", package="plm")

#Winsorize data  each year (over all firms) therefore split dataframe for each year and apply the winsorize function)

Grunfeld.w<-ddply(Grunfeld, .(year) function(x) winsorize(x$inv,x$value))

person Gritti    schedule 21.07.2014    source источник


Ответы (1)


Вы можете заранее создать список для хранения фреймов данных. Список должен иметь длину n, где n — количество уникальных значений в году.

library(plm)
library(robustHD)
data("Grunfeld", package="plm")

## determine unique values in year and their length
unique_years <- unique(Grunfeld$year)
n_unique_years <- length(unique_years)

## create an empty list of length 20
Grunfeld.w <- vector("list", length=n_unique_years)

for(i in 1:n_unique_years){
  Grunfeld.w[[i]]  <- winsorize(subset(Grunfeld, year==unique_years[i], 
                                       select=c(inv, value)))

  ## add the year field to each insorized data frame
  Grunfeld.w[[i]] <- cbind(Grunfeld.w[[i]], year=unique_years[i])
}

Теперь все данные winsorized хранятся в списке Grunfeld.w в виде фрейма данных. Если вам нужен только один фрейм данных, используйте следующее:

## convert the list to one data frame
temp <- data.frame(do.call("rbind", Grunfeld.w))

Что касается вашего второго вопроса, я предполагаю, что вы хотите выбрать «субъекты» на основе некоторой характеристики (например,> 5000 в x), но вы не хотите использовать функцию subset. Затем вы можете использовать функцию filter dplyr. Снова позвольте мне использовать данные Грюнфельда для иллюстрации:

library(dplyr)
Grunfeld_gt1940 <- filter(Grunfeld, year>1940) ## the "gt" stands for "greater than". 

Отредактировано

Если вы хотите упорядочить новые данные так же, как исходные данные, вы можете использовать rownames для извлечения исходного порядка:

temp <- temp[order(as.numeric(rownames(temp))), ]

## Add the winsorized variables to the original data
names(temp)[1:2] <- c("inv_wins", "value_wins")
Grunfeld_new <- data.frame(Grunfeld, temp[, c("inv_wins", "value_wins")])
person Masato Nakazawa    schedule 21.07.2014
comment
спасибо за ответ! Почему-то не работает преобразование в data.frame. Кроме того, как можно переупорядочить данные winsorized так же, как исходные данные? - person Gritti; 21.07.2014
comment
На самом деле do.call("rbind", Grunfeld.w) преобразует список в матрицу, а не в data.frame. Итак, я исправил эту ошибку. - person Masato Nakazawa; 21.07.2014
comment
Я попытался реализовать ваш код, но, к сожалению, он не совместим с моими NA, и я получаю следующую ошибку: Ошибка в собственном (R, симметричном = TRUE): бесконечные или отсутствующие значения в 'x' › traceback() 6: stop (infinite или отсутствующие значения в 'x') 5: собственный (R, симметричный = TRUE) 4: winsorize.matrix(as.matrix(x, ...)) 3: winsorize(as.matrix(x, ...)) 2: winsorize.data.frame(subset(mydata, time == unique_years[i], - person Gritti; 22.07.2014
comment
Вы можете удалить отсутствующие значения и применить winsorize. Затем включите na.omit в winsorize в цикле for. Я думаю, что это гораздо более экономно, чем, скажем, вменение отсутствующих данных, а затем их винсоризация, что трудно уложить в голове. - person Masato Nakazawa; 22.07.2014
comment
Куда бы вы включили na.omit и как вы можете удалить пропущенные значения до этого? Ваше здоровье - person Economist_Ayahuasca; 30.08.2017