Как вписать значения из групп в категорию с помощью `sapply ()`? - PullRequest
0 голосов
/ 28 мая 2018

Я хочу вменять пропуски в val всех ctry в cat1 с определенными ctry средствами.

Пример данных

set.seed(654)
df1 <- data.frame(
  year=rep(2000:2005, each=5),
  ctry=rep(LETTERS[1:5], 6),
  val=rnorm(30)
)
df1$cat <- ifelse(df1$ctry %in% c("A", "B"), 1, 0)
df1[sample(nrow(df1), 12), "val"] <- NA
> head(df1)
  year ctry         val cat
1 2000    A -0.76031762   1
2 2000    B -0.38970450   1
3 2000    C  1.68962523   0
4 2000    D          NA   0
5 2000    E  0.09530146   0
6 2001    A          NA   1

Сначала я получаю имена ctry в cat1 и распределяю их средства.

cat1 <- as.character(sort(unique(
  df1[!is.na(df1$val) & df1$cat == 1, ]
  [, 2])))
cat1 <- sapply(cat1, function(x) mean(df1$val[df1$ctry == x], na.rm=TRUE))
> cat1
        A         B 
0.4372003 0.4792314 

Теперь мне удается вручную навязать страну за страной:

df2 <- df1
df2$val[df2$ctry %in% names(cat1)[1] & is.na(df2$val)] <- cat1[1]
> head(df2)
  year ctry         val cat
1 2000    A -0.76031762   1
2 2000    B -0.38970450   1
3 2000    C  1.68962523   0
4 2000    D          NA   0
5 2000    E  0.09530146   0
6 2001    A -0.49758245   1

Но по какой-то причине я не могу заставить sapply() работать, чтобы выполнить вменение автоматически:

> sapply(seq_along(cat1), 
+        function(x) df2$val[df2$ctry %in% names(cat1)[x] & is.na(df2$val)] <- cat1[x])
         A          B 
-0.4975825 -0.6139364 

Ожидаемый результат будет представлять собой весь фрейм данных с конкретными вмененными средними значениями стран в категории cat1.

Ответы [ 3 ]

0 голосов
/ 28 мая 2018

если мое понимание верно, вы хотите автоматически последний процесс

sapply(seq_along(cat1), 
 function(x) df2$val[df2$ctry %in% names(cat1)[x] & is.na(df2$val)] <<- cat1[x])

> df2
   year ctry          val cat
1  2000    A -0.760317618   1
2  2000    B -0.389704501   1
3  2000    C  1.689625228   0
4  2000    D           NA   0
5  2000    E  0.095301460   0
6  2001    A -0.497582454   1
7  2001    B -0.613936417   1
8  2001    C           NA   0
9  2001    D           NA   0
10 2001    E           NA   0
11 2002    A -0.107260116   1
12 2002    B -0.838168333   1
13 2002    C -0.982605890   0
14 2002    D -0.820370986   0
15 2002    E -0.871432562   0
16 2003    A -0.497582454   1
17 2003    B -0.613936417   1
18 2003    C -0.006557849   0
19 2003    D  0.661696295   0
20 2003    E -0.762828067   0
21 2004    A -0.286692466   1
22 2004    B -0.613936417   1
23 2004    C  0.512579937   0
24 2004    D  0.722127317   0
25 2004    E           NA   0
26 2005    A -0.836059616   1
27 2005    B -0.613936417   1
28 2005    C  0.774016151   0
29 2005    D -0.691866605   0
30 2005    E           NA   0

Здесь я просто заменяю < на <<- назначение области видимости

0 голосов
/ 28 мая 2018

В базе R:

set.seed(654)
df1 <- data.frame(
  year=rep(2000:2005, each=5),
  ctry=rep(LETTERS[1:5], 6),
  val=rnorm(30)
)
df1$cat <- ifelse(df1$ctry %in% c("A", "B"), 1, 0)
df1[sample(nrow(df1), 12), "val"] <- NA

# want:
my_means <- tapply(df1$val, df1$ctry, mean, na.rm = TRUE)
df1$val <- ifelse(is.na(df1$val), my_means[df1$ctry], df1$val)
0 голосов
/ 28 мая 2018

Вы можете попробовать подход tidyverse, используя group_by, чтобы получить среднее значение для ctry.Затем обновите NA, используя ifelse.Добавлен новый столбец val2 для иллюстрации происходящего.Вы можете написать "val", чтобы переопределить столбец.

library(tidyverse)
df1 %>% 
  group_by(ctry) %>% 
  mutate(Mean=mean(val, na.rm = T)) %>% 
  mutate(val2=ifelse(is.na(val) & cat == 1, Mean, val)) %>% 
  ungroup()
# A tibble: 30 x 6
    year ctry       val   cat    Mean     val2
   <int> <fct>    <dbl> <dbl>   <dbl>    <dbl>
 1  2000 A      -0.760      1 -0.498   -0.760 
 2  2000 B      -0.390      1 -0.614   -0.390 
 3  2000 C       1.69       0  0.397    1.69  
 4  2000 D      NA          0 -0.0321  NA     
 5  2000 E       0.0953     0 -0.513    0.0953
 6  2001 A      NA          1 -0.498   -0.498 
 7  2001 B      NA          1 -0.614   -0.614 
 8  2001 C      NA          0  0.397   NA     
 9  2001 D      NA          0 -0.0321  NA     
10  2001 E      NA          0 -0.513   NA     
# ... with 20 more rows
...