как я могу преобразовать значения в значение, разделенное двоеточием (двойная точка)

#r

#r

Вопрос:

У меня есть такие данные

 df<- structure(list(df = structure(c(10L, 8L, 2L, 8L, 7L, 7L, 10L, 
8L, 3L, 10L, 10L, 9L, 9L, 1L, 1L, 3L, 1L, 5L, 5L, 4L, 10L, 8L, 
1L, 1L, 2L, 6L), .Label = c("-1:-1:2", "-1:2:-1", "-1:2:2", "1:01:01", 
"1:1(2):1", "1(1)|1(2):1(1)|1(2):1(1)|1(2)", "1(1)|1(2):2:2", 
"2:-1:-1", "2:-1:2", "2:02:02"), class = "factor")), class = "data.frame", row.names = c(NA, 
-26L))
  

Я хочу преобразовать его в слова, как я определяю. Я хочу иметь столько столбцов, сколько двойных точек, например, здесь у нас их три: поэтому мы добавим 3 столбца после df. Затем мы заполняем его словами

 2 = Homo
-1 = No
1= Het
1(1)= Het1 
1(2)= Het2  
  

Итак, ожидаемый результат выглядит следующим образом.

 2:02:02 Homo    Homo    Homo
2:-1:-1 Homo    No  No
-1:2:-1 No  Homo    No
2:-1:-1 Homo    No  No
1(1)|1(2):2:2   Het1 Het2   Homo    Homo
1(1)|1(2):2:2   Het1 Het2   Homo    Homo
2:02:02 Homo    Homo    Homo
2:-1:-1 Homo    No  No
-1:2:2  No  Homo    Homo
2:02:02 Homo    Homo    Homo
2:02:02 Homo    Homo    Homo
2:-1:2  Homo    No  Homo
2:-1:2  Homo    No  Homo
-1:-1:2 No  No  Homo
-1:-1:2 No  No  Homo
-1:2:2  No  Homo    Homo
-1:-1:2 No  No  Homo
1:1(2):1    Het Het2    Het
1:1(2):1    Het Het3    Het
1:01:01 Het Het Het
2:02:02 Homo    Homo    Homo
2:-1:-1 Homo    No  No
-1:-1:2 No  No  Homo
-1:-1:2 No  No  Homo
-1:2:-1 No  Homo    No
1(1)|1(2):1(1)|1(2):1(1)|1(2)   Het1 Het2   Het1 Het2   Het1 Het2 
  

Комментарии:

1. Под «двойными точками» вы подразумеваете двоеточие? Это региональный термин? Никогда не слышал об этом в США

2. @camille В Португалии это «dois pontos» , что означает «две точки» .

3. @Camille Я имел в виду :

4. Будут ли 02 и 2 совпадать с одной и той же строкой?

5. @akrun Да, 02 и 2 совпадают

Ответ №1:

Не уверен, что результат — это именно то, что вам нужно, но, возможно, это могло бы помочь. Я также думаю, что, возможно, это не самое эффективное и красивое решение, но оно может стать отправной точкой.

Однако я вызвал dats ваши данные:

 head(dats)
                              df
1                        2:02:02
2                        2:-1:-1
3                        -1:2:-1
4                        2:-1:-1
5                  1(1)|1(2):2:2
6                  1(1)|1(2):2:2
  

И я создал сопоставление data.frame :

 mapping
    id value
1    2  Homo
2   -1    No
3    1   Het
4 1(1)  Het1
5 1(2)  Het2
  

Сначала я разделил с stringr::str_split_fixed() двойными точками:

 library(stringr)
double_point <- as.data.frame.matrix(str_split_fixed(dats$df, ":", 3))
  

Теперь мы должны разделить значения для каждого столбца на | :

 listed <- list() # empty list 
for (i in (1:ncol(double_point))){
  listed[[i]] <- (double_point[,i])
  listed[[i]] <- str_split_fixed(listed[[i]], "\|", 2)
}

# put as data frame
df_ <- do.call(cbind, listed)

# this is going to help in the future
df_1 <- df_

# result till now:
head(df_1)
     [,1]   [,2]   [,3] [,4] [,5] [,6]
[1,] "2"    ""     "02" ""   "02" ""  
[2,] "2"    ""     "-1" ""   "-1" ""  
[3,] "-1"   ""     "2"  ""   "-1" ""  
[4,] "2"    ""     "-1" ""   "-1" ""  
[5,] "1(1)" "1(2)" "2"  ""   "2"  ""  
[6,] "1(1)" "1(2)" "2"  ""   "2"  ""
  

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

 listed <- list()

for (i in (1:ncol(df_))){
  df_[,i] <-  gsub("0","",df_[,i])
  listed[[i]] <- mapping[match(df_[,i], mapping$id), 2, drop=F]
}

df_final <- cbind(df_1,do.call(cbind, listed))
head(df_final)
       1    2  3 4  5 6 value value value value value value
1      2      02   02    Homo  <NA>  Homo  <NA>  Homo  <NA>
1.1    2      -1   -1    Homo  <NA>    No  <NA>    No  <NA>
2     -1       2   -1      No  <NA>  Homo  <NA>    No  <NA>
1.2    2      -1   -1    Homo  <NA>    No  <NA>    No  <NA>
4   1(1) 1(2)  2    2    Het1  Het2  Homo  <NA>  Homo  <NA>
4.1 1(1) 1(2)  2    2    Het1  Het2  Homo  <NA>  Homo  <NA>
  

Надеюсь, это поможет!

Редактировать

Здесь отображение dput() и str() :

 dput(mapping)
structure(list(id = structure(c(5L, 1L, 2L, 3L, 4L), .Label = c("-1", 
"1", "1(1)", "1(2)", "2"), class = "factor"), value = structure(c(4L, 
5L, 1L, 2L, 3L), .Label = c("Het", "Het1", "Het2", "Homo", "No"
), class = "factor")), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5"))

str(mapping)
'data.frame':   5 obs. of  2 variables:
 $ id   : Factor w/ 5 levels "-1","1","1(1)",..: 5 1 2 3 4
 $ value: Factor w/ 5 levels "Het","Het1","Het2",..: 4 5 1 2 3
  

Комментарии:

1. Спасибо, ваш код не печатает для 1 (1) или 1 (2) . не могли бы вы, пожалуйста, сообщить мне str сопоставления?

2. Привет, опубликовал редактирование. Кажется, что в последних строках последнего вывода он печатает для упомянутых вами случаев.

Ответ №2:

Вы можете явно определить все возможные значения в num2words фрейме данных, а затем выполнить следующее

 df<- structure(list(df = structure(c(10L, 8L, 2L, 8L, 7L, 7L, 10L, 
                                     8L, 3L, 10L, 10L, 9L, 9L, 1L, 1L, 3L, 1L, 5L, 5L, 4L, 10L, 8L, 
                                     1L, 1L, 2L, 6L), .Label = c("-1:-1:2", "-1:2:-1", "-1:2:2", "1:01:01", 
                                                                 "1:1(2):1", "1(1)|1(2):1(1)|1(2):1(1)|1(2)", "1(1)|1(2):2:2", 
                                                                 "2:-1:-1", "2:-1:2", "2:02:02"), class = "factor")), class = "data.frame", row.names = c(NA, 
                                                                                                                                                          -26L))
num2words <- read.table(text = "
                        num word
                        2 Homo
                        02  Homo
                        -1  No
                        1 Het
                        01  Het                        
                        1(1)  Het1
                        1(2)  Het2
                        1(1)|1(2) Het1-Het2
                        1(2)|1(1) Het2-Het1
                        ", header = T, stringsAsFactors = F)

lst=lapply(1:nrow(df), function(x) {
  split.nums <- unlist(strsplit(as.character(df[x,]), ":"))
  num2words$word[match(split.nums, num2words$num)]
})

new.df=cbind(df, do.call(rbind, lst))

> new.df

                              df         1         2         3
1                        2:02:02      Homo      Homo      Homo
2                        2:-1:-1      Homo        No        No
3                        -1:2:-1        No      Homo        No
4                        2:-1:-1      Homo        No        No
5                  1(1)|1(2):2:2 Het1-Het2      Homo      Homo
6                  1(1)|1(2):2:2 Het1-Het2      Homo      Homo
7                        2:02:02      Homo      Homo      Homo
8                        2:-1:-1      Homo        No        No
9                         -1:2:2        No      Homo      Homo
10                       2:02:02      Homo      Homo      Homo
11                       2:02:02      Homo      Homo      Homo
12                        2:-1:2      Homo        No      Homo
13                        2:-1:2      Homo        No      Homo
14                       -1:-1:2        No        No      Homo
15                       -1:-1:2        No        No      Homo
16                        -1:2:2        No      Homo      Homo
17                       -1:-1:2        No        No      Homo
18                      1:1(2):1       Het      Het2       Het
19                      1:1(2):1       Het      Het2       Het
20                       1:01:01       Het       Het       Het
21                       2:02:02      Homo      Homo      Homo
22                       2:-1:-1      Homo        No        No
23                       -1:-1:2        No        No      Homo
24                       -1:-1:2        No        No      Homo
25                       -1:2:-1        No      Homo        No
26 1(1)|1(2):1(1)|1(2):1(1)|1(2) Het1-Het2 Het1-Het2 Het1-Het2