Векторизация замены имени по диапазону столбцов - PullRequest
0 голосов
/ 26 января 2019

У меня большой набор данных, так что это игрушечный пример.

Вот кадр данных df

structure(list(Target = structure(c(1L, 4L, 5L, 2L, 3L), .Label = c("Jim", 
"Kurt", "Lester", "Tara", "Taylor"), class = "factor"), Gender = structure(c(2L, 
1L, 1L, 2L, 2L), .Label = c("F", "M"), class = "factor"), Partner1 = structure(c(1L, 
4L, 4L, 2L, 3L), .Label = c("Andrew", "Jim", "Mickey", "Taylor"
), class = "factor"), Partner2 = structure(c(2L, 3L, 1L, 4L, 
3L), .Label = c("Andrew", "Jim", "Kurt", "Mickey"), class = "factor"), 
    Partner4 = structure(c(4L, 3L, 2L, 3L, 1L), .Label = c("Andrew", 
    "Jim", "Lester", "Tara"), class = "factor")), class = "data.frame", row.names = c(NA, 
-5L))

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

structure(list(name = structure(c(2L, 5L, 1L, 6L, 4L, 3L), .Label = c("Andrew", 
"Jim", "Kurt", "Lester", "Mickey", "Taylor"), class = "factor"), 
    id = structure(c(2L, 5L, 1L, 6L, 4L, 3L), .Label = c("A3", 
    "J9", "K5", "L4", "M4", "T7"), class = "factor")), class = "data.frame", row.names = c(NA, 
-6L))

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

df[["Partner1"]] <- key[ match(df[['Partner1']], key[['name']] ) , 'id']

, но я бы хотел векторизовать его, чтобы я мог перекодировать каждое имявнутри ключа к его соответствующему идентификатору во всех параллельных столбцах

Реальные данные будут сотнями столбцов, и около 30 из этих столбцов будут теми, которые я хочу де-идентифицировать

Любые предложения?

Ответы [ 3 ]

0 голосов
/ 26 января 2019

Возможное решение в базе R:

# column names to replace
cols <- c('Target','Partner1','Partner2','Partner4')
# convert df subset to a matrix of characters
mx <- as.matrix(df[,cols])
# get the replacements values using match
repl <- as.character(key$id)[match(mx,as.character(key$name))]
# substitute NA's in replacements with the original values
repl[is.na(repl)] <- mx[is.na(repl)]
# create a copy of df
df2 <- df
# replace the values of df2 with the replacements
df2[,cols] <- repl

Результат:

> df2
  Target Gender Partner1 Partner2 Partner4
1     J9      M       A3       J9     Tara
2   Tara      F       T7       K5       L4
3     T7      F       T7       A3       J9
4     K5      M       J9       M4       L4
5     L4      M       M4       K5       A3
0 голосов
/ 26 января 2019

Другая база R решение:

# Create lookup vector
lu_vect <- setNames(as.character(df2[["id"]]), df2[["name"]])
lu_vect
#   Jim Mickey Andrew Taylor Lester   Kurt 
#  "J9"   "M4"   "A3"   "T7"   "L4"   "K5"

# Make a list of columns we want to *update*
cols_to_anonymise <- c("Target", "Partner1", "Partner2", "Partner4")

# Anonymise column by column, if name is not in key, replace by NA
df[cols_to_anonymise] <- lapply(
  df[cols_to_anonymise],
  function(x) lu_vect[as.character(x)]
)

# Print out results
df
#   Target Gender Partner1 Partner2 Partner4
# 1     J9      M       A3       J9     <NA>
# 2   <NA>      F       T7       K5       L4
# 3     T7      F       T7       A3       J9
# 4     K5      M       J9       M4       L4
# 5     L4      M       M4       K5       A3
0 голосов
/ 26 января 2019

Одна возможность с использованием tidyverse:

df %>%
 rowid_to_column() %>%
 gather(var, val, -rowid) %>%
 left_join(df2, by = c("val" = "name")) %>%
 mutate(val = ifelse(var == "Gender", val, 
                     ifelse(!is.na(id), paste0(id), NA_character_))) %>%
 select(-id) %>%
 spread(var, val) %>%
 select(-rowid)

  Gender Partner1 Partner2 Partner4 Target
1      M       A3       J9     <NA>     J9
2      F       T7       K5       L4   <NA>
3      F       T7       A3       J9     T7
4      M       J9       M4       L4     K5
5      M       M4       K5       A3     L4

Сначала выполняется преобразование данных большой длины.Во-вторых, он соединяет преобразованный df с df2.Если в df2 есть идентификатор для имени в df, он заменяет имя в df на этот идентификатор, в противном случае - на NA.Наконец, он преобразует данные обратно в исходный формат.

Или базовое решение R:

data.frame(apply(df[, -2], 2, function(x) as.character(df2$id)[match(x, as.character(df2$name))]),
           Gender = df[, 2])

  Target Partner1 Partner2 Partner4 Gender
1     J9       A3       J9     <NA>      M
2   <NA>       T7       K5       L4      F
3     T7       T7       A3       J9      F
4     K5       J9       M4       L4      M
5     L4       M4       K5       A3      M
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...