Объединенная комбинация всех столбцов в кадре данных (R) - PullRequest
0 голосов
/ 14 января 2019

Я хотел бы объединить столбцы без повторения комбинации столбцов. У меня есть пример ниже, чтобы объяснить, что я пытаюсь сделать

Предположим, что у меня есть фрейм данных с 3 столбцами, и я хотел бы создать больше столбцов (которые представляют собой комбинацию из 2) на основе исходных столбцов в виде объединения двух столбцов

Пример df

V1 <- as.character(c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B"))
V2 <- as.character(c("No","Yes","Yes","No","No","No","Yes","Yes","Yes","No"))
V3 <- as.character(c('Alpha',"Yes",'NA','Beta','NA',"Yes",'NA',"Yes","Yes",
'Something','Else'))

df_sample <- as.data.frame(cbind(V1, V2, V3))
df_sample

Теперь я хотел бы получить следующее в качестве вывода для новых столбцов (показывая результаты для первых 2 строк и имена нужных столбцов)

V1_V2  V1_V3    V2_V3
A_NO   A_Alpha  No_Alpha
A_Yes  A_Yes    Yes_Yes

Я попытался создать цикл со следующей функцией, но у меня есть 5 новых столбцов вместо 3, как V1_V3 повторяется с V3_V1. Я пытаюсь понять, как мы можем это исправить. Также, если есть лучший способ для решения

str_eval=function(x) {return(eval(parse(text=x)))}

cat_cols <- c('V1','V2','V3')

for (i in (1:length(cat_cols))){
  for (j in (1:length(cat_cols))){
    if (i != j){
      col_name <- paste(colnames(df_sample)[i],"_",colnames(df_sample)[j],sep="")
      assign(col_name,
         paste(df_sample[,cat_cols[i]],'_',df_sample[,cat_cols[j]],sep=""))
      df_sample <- cbind(df_sample, str_eval(col_name))
      colnames(df_sample)[ncol(df_sample)] <- paste(col_name)
      rm(col_name)
    }
  }
}

Ответы [ 2 ]

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

Нет необходимости в петлях. Это может быть векторизовано с использованием sapply и combn с paste. Это также примерно в 20 раз быстрее, чем использование цикла, основанного на тесте производительности.

cols_to_paste <- 2 #number of columns you want to paste together.
sapply(1:ncol(combn(names(df_sample), cols_to_paste)), function(x){
      do.call(paste, c(df_sample[, combn(names(df_sample), cols_to_paste)[,x]], sep="_"))} )

      [,1]    [,2]          [,3]          
 [1,] "A_No"  "A_Alpha"     "No_Alpha"    
 [2,] "A_Yes" "A_Yes"       "Yes_Yes"     
 [3,] "A_Yes" "A_NA"        "Yes_NA"      
 [4,] "A_No"  "A_Beta"      "No_Beta"     
 [5,] "A_No"  "A_NA"        "No_NA"       
 [6,] "B_No"  "B_Yes"       "No_Yes"      
 [7,] "B_Yes" "B_NA"        "Yes_NA"      
 [8,] "B_Yes" "B_Yes"       "Yes_Yes"     
 [9,] "B_Yes" "B_Yes"       "Yes_Yes"     
[10,] "B_No"  "B_Something" "No_Something"
[11,] "A_No"  "A_Else"      "No_Else"
0 голосов
/ 14 января 2019

Изменение вашего soln

    V1 <- as.character(c("A", "A", "A", "A", "A", "B", "B", "B", "B", "B"))
    V2 <- as.character(c("No","Yes","Yes","No","No","No","Yes","Yes","Yes","No"))
    V3 <- as.character(c('Alpha',"Yes",'NA','Beta','NA',"Yes",'NA',"Yes","Yes",
                         'Something'))
    V4 = 1:10
    V5 = 10:1

    df_sample <- as.data.frame(cbind(V1, V2, V3, V4, V5))
    df_sample

    str_eval=function(x) {return(eval(parse(text=x)))}

    cat_cols <- c('V1','V2','V3','V4','V5')

    for (i in (1:length(cat_cols))){
      if(i < length(cat_cols)){
      for (j in (i+1):length(cat_cols)){
          col_name <- paste(colnames(df_sample)[i],"_",colnames(df_sample)[j],sep="")
          assign(col_name,
                 paste(df_sample[,cat_cols[i]],'_',df_sample[,cat_cols[j]],sep=""))
          df_sample <- cbind(df_sample, str_eval(col_name))
          colnames(df_sample)[ncol(df_sample)] <- paste(col_name)
          rm(col_name)
        }
      }
    }

    head(df_sample)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...