У меня есть фрейм данных с несколькими столбцами, и я создаю новый столбец, который случайным образом выбирает одно значение из любого из других столбцов. Как я могу отследить, из какого столбца взято значение?

Я видел точно такой же вопрос и решение здесь < / a>, но он написан на Python и не смог найти эквивалент R.

Данные 1 :: каждая строка имеет разные значения в столбцах

df_uniques <-
  data.frame(
    col_a = c(2, 2, 5, 5, 3),
    col_b = c(NA, 4, 2, 3, 1),
    col_c = c(4, 5, 3, 1, 2),
    col_d = c(1, NA, 4, 2, 4),
    col_e = c(3, 3, 1, 4, 5)
  )

> df_uniques

##   col_a col_b col_c col_d col_e
## 1     2    NA     4     1     3
## 2     2     4     5    NA     3
## 3     5     2     3     4     1
## 4     5     3     1     2     4
## 5     3     1     2     4     5

Заменить новый столбец на выборку из любого из предыдущих столбцов

library(dplyr)

set.seed(2020)

df_uniques %>%
  rowwise() %>%
  mutate(sampled = sample(c(col_a, col_b, col_c, col_d, col_e), size = n()))

## # A tibble: 5 x 6
## # Rowwise: 
##   col_a col_b col_c col_d col_e sampled
##   <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl>
## 1     2    NA     4     1     3       1
## 2     2     4     5    NA     3      NA
## 3     5     2     3     4     1       5
## 4     5     3     1     2     4       5
## 5     3     1     2     4     5       4

Данные 2 :: каждая строка имеет повторяющиеся значения в столбцах

df_duplicates <-
  data.frame(
    col_a = c(1, 4, 2, 5, 2),
    col_b = c(NA, 4, NA, 3, 1),
    col_c = c(4, NA, 5, NA, NA),
    col_d = c(1, NA, NA, 2, NA),
    col_e = c(2, 3, NA, NA, 5)
  )

> df_duplicates
##   col_a col_b col_c col_d col_e
## 1     1    NA     4     1     2     
## 2     4     4    NA    NA     3
## 3     2    NA     5    NA    NA
## 4     5     3    NA     2    NA
## 5     2     1    NA    NA     5

Заменить новый столбец на выборку из любого из предыдущих столбцов

set.seed(2020)

df_duplicates %>%
  rowwise() %>%
  mutate(sampled = sample(c(col_a, col_b, col_c, col_d, col_e), size = n()))

## # A tibble: 5 x 6
## # Rowwise: 
##   col_a col_b col_c col_d col_e sampled
##   <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl>
## 1     1    NA     4     1     2      NA
## 2     4     4    NA    NA     3       4
## 3     2    NA     5    NA    NA      NA
## 4     5     3    NA     2    NA       3
## 5     2     1    NA    NA     5       1

Отслеживание: какой столбец является источником sampled?

Желаемый результат (данные 1 :: уникальные посетители)

# A tibble: 5 x 7
# Rowwise: 
  col_a col_b col_c col_d col_e sampled origin_col
  <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl> <chr>     
1     2    NA     4     1     3       1 col_d     
2     2     4     5    NA     3      NA col_d     
3     5     2     3     4     1       5 col_a     
4     5     3     1     2     4       5 col_a     
5     3     1     2     4     5       4 col_d 

Желаемый результат (данные 2 :: дубликаты)

# A tibble: 5 x 7
# Rowwise: 
  col_a col_b col_c col_d col_e sampled origin_col   
  <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl> <chr>        
1     1    NA     4     1     2       1 col_a, col_d
2     4     4    NA    NA     3      NA col_c, col_d 
3     2    NA     5    NA    NA       2 col_a        
4     5     3    NA     2    NA       5 col_a        
5     2     1    NA    NA     5      NA col_c, col_d 

2
Emman 10 Ноя 2020 в 14:02

2 ответа

Лучший ответ

Вы ищете что-то подобное?

cols <- c("col_a", "col_b", "col_c", "col_d", "col_e")
workflow <- 
  . %>%
  rowwise() %>%
  mutate(
    sampled = sample(c_across(!!cols), 1L), 
    origin_col = toString(cols[which(c_across(!!cols) %in% sampled)])
  )

Выход

> set.seed(2020L); workflow(df_uniques)
# A tibble: 5 x 7
# Rowwise: 
  col_a col_b col_c col_d col_e sampled origin_col
  <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl> <chr>       
1     2    NA     4     1     3       1 col_d       
2     2     4     5    NA     3      NA col_d       
3     5     2     3     4     1       5 col_a       
4     5     3     1     2     4       5 col_a       
5     3     1     2     4     5       4 col_d       

> set.seed(2020L); workflow(df_duplicates)
# A tibble: 5 x 7
# Rowwise: 
  col_a col_b col_c col_d col_e sampled origin_col
  <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl> <chr>       
1     1    NA     4     1     2       1 col_a, col_d
2     4     4    NA    NA     3      NA col_c, col_d
3     2    NA     5    NA    NA       2 col_a       
4     5     3    NA     2    NA       5 col_a       
5     2     1    NA    NA     5      NA col_c, col_d

Метод 1: создайте временную переменную для выбранных столбцов

workflow <- 
  . %>%
  rowwise() %>%
  mutate(
    d = across(starts_with("col_")),
    sampled = sample(c_across(names(d)), 1L),
    original_col = toString(names(d)[which(c_across(names(d)) %in% sampled)]), 
    d = NULL
  )

Метод 2: оберните все в функцию

workflow <- function(df) {
  cols <- names(df)
  cols <- cols[starts_with("col_", vars = cols)]
  # or cols <- cols[startsWith(cols, "col_")]
  # or cols <- cols[grepl("^col_", cols)]
  # ...
  df %>%
    rowwise() %>%
    mutate(
      sampled = sample(c_across(!!cols), 1L),
      original_col = toString(cols[which(c_across(!!cols) %in% sampled)]),
    )
}

Я предпочитаю второй метод, так как он более гибкий.

1
ekoam 10 Ноя 2020 в 13:34

Один из вариантов может быть:

df_duplicates %>%
 rowwise() %>%
 mutate(sampled = sample(c_across(col_a:col_e), size = n()),
        origin_col = if(is.na(sampled)) toString(names(.)[which(is.na(c_across(col_a:col_e)))]) else toString(names(.)[which(c_across(col_a:col_e) == sampled)]))
     
  col_a col_b col_c col_d col_e sampled origin_col         
  <dbl> <dbl> <dbl> <dbl> <dbl>   <dbl> <chr>              
1     1    NA     4     1     2       1 col_a, col_d       
2     4     4    NA    NA     3       4 col_a, col_b       
3     2    NA     5    NA    NA      NA col_b, col_d, col_e
4     5     3    NA     2    NA      NA col_c, col_e       
5     2     1    NA    NA     5       2 col_a  
1
tmfmnk 10 Ноя 2020 в 11:18