2016-12-07 3 views
1

У меня есть фрейм данных с продольной структурой следующим образом:R - Recode Н.А. с уровнями фактора в сгруппированных данных

df = structure(list(oslaua = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("E06000001", "E06000002", 
"E06000003", "E06000004"), class = "factor"), wave = structure(c(1L, 
2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L), .Label = c("0", 
"1", "2", "3"), class = "factor"), old.la = structure(c(1L, 1L, 
NA, 1L, 2L, 2L, 2L, NA, 3L, 3L, 3L, 3L, 4L, 4L, NA), .Label = c("00EB", 
"00EC", "00EE", "00EF"), class = "factor"), la = structure(c(1L, 
1L, NA, 1L, 2L, 2L, 2L, NA, 3L, 3L, 3L, 3L, 4L, 4L, NA), .Label = c("Hartlepool UA", 
"Middlesbrough UA", "Redcar and Cleveland UA", "Stockton-on-Tees UA" 
), class = "factor"), dclg.code = structure(c(1L, 1L, NA, 1L, 
4L, 4L, 4L, NA, 3L, 3L, 3L, 3L, 2L, 2L, NA), .Label = c("H0724", 
"H0738", "V0728", "W0734"), class = "factor"), novo_entries = c(24L, 
4L, 0L, 1L, 35L, 15L, 1L, 0L, 49L, 7L, 2L, 2L, 40L, 14L, 0L)), .Names = c("oslaua", 
"wave", "old.la", "la", "dclg.code", "novo_entries"), row.names = c(NA, 
15L), class = "data.frame") 

Моим идентификатором переменным является oslaua и мое переменное время wave. old.la, la и dclg.code являются переменными фактора, которые имеют NA. Моя цель состоит из перекодировки моего NA с уровнем каждой переменной, связанной с каждым идентификатором (oslaua). Я пытался сделать это для случая old.la используя следующее:

df = df %>% group_by(oslaua) %>% mutate(old.la.1 = ifelse(is.na(old.la), unique(old.la), old.la)) %>% as.data.frame() 

Я частично получить свою цель, но есть некоторые вопросы, как вы можете видеть:

> df 
     oslaua wave old.la      la dclg.code novo_entries old.la.1 
1 E06000001 0 00EB   Hartlepool UA  H0724   24  1 
2 E06000001 1 00EB   Hartlepool UA  H0724   4  1 
3 E06000001 2 <NA>     <NA>  <NA>   0  2 
4 E06000001 3 00EB   Hartlepool UA  H0724   1  1 
5 E06000002 0 00EC  Middlesbrough UA  W0734   35  2 
6 E06000002 1 00EC  Middlesbrough UA  W0734   15  2 
7 E06000002 2 00EC  Middlesbrough UA  W0734   1  2 
8 E06000002 3 <NA>     <NA>  <NA>   0  2 
9 E06000003 0 00EE Redcar and Cleveland UA  V0728   49  3 
10 E06000003 1 00EE Redcar and Cleveland UA  V0728   7  3 
11 E06000003 2 00EE Redcar and Cleveland UA  V0728   2  3 
12 E06000003 3 00EE Redcar and Cleveland UA  V0728   2  3 
13 E06000004 0 00EF  Stockton-on-Tees UA  H0738   40  4 
14 E06000004 1 00EF  Stockton-on-Tees UA  H0738   14  4 
15 E06000004 2 <NA>     <NA>  <NA>   0  4 

конкретнее, уровни факторы меняют свой формат, а также в некоторых случаях ошибки перекодируются неправильно (например, oslaua = E06000001 - ряд 3)

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

Любые предложения для решения этих вопросов действительно оценены.

Спасибо!

ответ

3

Вот еще один вариант с использованием data.table

library(data.table) 
setDT(df)[, old.la1 := levels(droplevels(old.la)), by = oslaua] 

Для нескольких столбцов

nm1 <- c("old.la", "la", "dclg.code") 
df1 <- setDT(df)[, lapply(.SD, function(x) levels(droplevels(x))[1]) , 
     by = oslaua, .SDcols = nm1][df, on = "oslaua"] 
df1[, !grepl("i\\.", names(df1)), with = FALSE] 

Наша первоначальная идея была

setDT(df)[, (nm1) := lapply(.SD, function(x) 
    factor(levels(droplevels(x)))) , by = oslaua, .SDcols = nm1] 

Но по какой-то причине, преобразование в factor внутри каждой группы получает некоторый странный вывод, имеющий только один уровень для каждого столбца в выходных данных (с использованием v1.10.0)

+1

Большое спасибо @akrun, это именно то, что мне нужно. Я все еще не понимаю, почему он изменил формат фактора, когда я применял свое решение. – Edu

+1

@Edu Изменено на 'character', но после' df1' вы можете переконвертировать столбцы в 'factor', то есть' df2 <- df1 [,! Grepl ("i \\.", Names (df1)), с = FALSE]; df2 [, (nm1): = lapply (.SD, factor), .SDcols = nm1] ' – akrun

1

Это должно работать для вас:

library(zoo) 

df %>% 
    group_by(oslaua) %>% 
    mutate(old.la.1 = na.locf(old.la)) 

Он использует последний zoo «s переноситься функцию для замены НС-х. Это безопасный тип. В вашем коде ifelse строит два вектора (один для случая, когда тест разрешается до TRUE, а другой - при его разрешении до FALSE. Для обеспечения совместимости кажется, что ifelse уменьшает каждый из них до самого простого, общего типа. В случае факторов, это целое число (запустить typeof(df$old.la).

+0

Это работает только в том случае, если значение NA никогда не является первым из его группы, нет? – mpjdem

+0

Вы правы. Это можно было бы смягчить, используя 'arr' (форсируя' NA' до конца), но, вероятно, не идеальное решение. Решение akrun также может быть реализовано в рамках 'dplyr'. – Benjamin

+0

Это можно исправить, используя 'na.aggregate' вместо' na.locf'. –

0

с другой стороны, более элегантное решение, которое позволяет избежать создания новых переменных будет использовать fill() из tidyr:

data = data %>% group_by(oslaua) %>% fill(old.la, la, dclg.code) 
data 

Которые доходы:

> data 
Source: local data frame [15 x 6] 
Groups: oslaua [4] 

     oslaua wave old.la      la dclg.code novo_entries 
     <fctr> <fctr> <fctr>     <fctr> <fctr>  <int> 
1 E06000001  0 00EB   Hartlepool UA  H0724   24 
2 E06000001  1 00EB   Hartlepool UA  H0724   4 
3 E06000001  2 00EB   Hartlepool UA  H0724   0 
4 E06000001  3 00EB   Hartlepool UA  H0724   1 
5 E06000002  0 00EC  Middlesbrough UA  W0734   35 
6 E06000002  1 00EC  Middlesbrough UA  W0734   15 
7 E06000002  2 00EC  Middlesbrough UA  W0734   1 
8 E06000002  3 00EC  Middlesbrough UA  W0734   0 
9 E06000003  0 00EE Redcar and Cleveland UA  V0728   49 
10 E06000003  1 00EE Redcar and Cleveland UA  V0728   7 
11 E06000003  2 00EE Redcar and Cleveland UA  V0728   2 
12 E06000003  3 00EE Redcar and Cleveland UA  V0728   2 
13 E06000004  0 00EF  Stockton-on-Tees UA  H0738   40 
14 E06000004  1 00EF  Stockton-on-Tees UA  H0738   14 
15 E06000004  2 00EF  Stockton-on-Tees UA  H0738   0 
Смежные вопросы