Проблема с вставкой 5 групп столбцов в R - PullRequest
0 голосов
/ 07 декабря 2018

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

Table:

V29  V30  V31  V32  V33  V34 V35 V36 V37 V38 .... V69
044  N    005  E    026  044 N   006 E   011 

Я хочу вставить их в 5 групп столбцов, начиная с V29.Например, я хочу получить выходной столбец в Table, как показано ниже.

Table:
V29  V30  V31  V32  V33  V34 V35 V36 V37 V38 .... V69   Output
044  N    005  E    026  044 N   006 E   011            044N005E026-044N006E011-

Как мне добиться этого в R. Любая помощь приветствуется.

Спасибо.

Ответы [ 2 ]

0 голосов
/ 07 декабря 2018

Используя DF, определенный в конце заметки, создайте строку форматирования sprintf fmt и запустите ее.

Если в DF есть NA, то они будут отображаться в выходных данных в виде строки "NA".Если вы предпочитаете опустить их полностью, замените их пустой строкой в ​​DF перед запуском приведенного ниже кода, то есть сначала выполните DF[is.na(DF)] <- "".

fmt <- paste(rep(strrep("%s", 5), ncol(DF)/5), collapse = "-") # %s%s%s%s%s-%s%s%s%s%s
Output <- do.call("sprintf", c(fmt, DF))
data.frame(DF, Output, stringsAsFactors = FALSE)

, что дает:

  V29 V30 V31 V32 V33 V34 V35 V36 V37 V38                  Output
1 044   N 005   E 026 044   N 006   E 011 044N005E026-044N006E011

или используя DF2 из Note вместо DF, мы получаем:

  V29 V30 V31 V32 V33 V34 V35 V36 V37 V38                  Output
1 044   N 005   E 026 044   N 006   E 011 044N005E026-044N006E011
2 045   S 006   F 027 045   S 007   F 012 045S006F027-045S007F012

data.table

Если, согласно комментарию, вы хотите использовать data.table, тогда используйтеэто (с fmt сверху):

library(data.table)

DT <- data.table(DF)
DT[, Output:=do.call("sprintf", c(fmt, .SD))]

Примечание

Lines <- "
  V29  V30  V31  V32  V33  V34 V35 V36 V37 V38 
  044  N    005  E    026  044 N   006 E   011 "
DF <- read.table(text = Lines, header = TRUE, colClasses = "character")

Lines2 <- "
  V29 V30 V31 V32 V33 V34 V35 V36 V37 V38
1 044   N 005   E 026 044   N 006   E 011
2 045   S 006   F 027 045   S 007   F 012"
DF2 <- read.table(text = Lines2, header = TRUE, colClasses = "character")
0 голосов
/ 07 декабря 2018

Немного расширяя ваши данные:

x <- read.table(stringsAsFactors=FALSE, header=TRUE, as.is=TRUE, colClasses="character", text="
V29  V30  V31  V32  V33  V34 V35 V36 V37 V38    V29a V30a V31a V32a V33a V34a V35a V36a V37a V38a
044  N    005  E    026  044 N   006 E   011    044  N    005  E    026  044  N    006  E    011 
044  N    005  E    026  044 N   006 E   011    044  N    005  E    026  044  N    006  E    011 ")

Ответ:

sapply(split.default(x, (seq_len(ncol(x))-1) %/% 5),
       function(s) paste(apply(s, 1, paste0, collapse = ""), collapse = "-"))
#                         0                         1                         2 
# "044N005E026-044N005E026" "044N006E011-044N006E011" "044N005E026-044N005E026" 
#                         3 
# "044N006E011-044N006E011" 

Это можно легко присвоить столбцу того же кадра.

Объяснение:

  • , чтобы разбить кадр на 5 столбцов, на ум приходит split, но при использовании по умолчанию split(...) будет использоваться split.data.frame, который разбивается на строку , а не столбец , поэтому мы используем split.default (работает по столбцам).Оттуда вы можете увидеть, как мы группируем вещи:

    (seq_len(ncol(x))-1) %/% 5
    #  [1] 0 0 0 0 0 1 1 1 1 1 2 2 2 2 2 3 3 3 3 3
    
  • Для каждой из этих групп мы получаем 5-колоночный фрейм:

    split.default(x, (seq_len(ncol(x))-1) %/% 5)
    # $`0`
    #   V29 V30 V31 V32 V33
    # 1  44   N   5   E  26
    # 2  44   N   5   E  26
    # $`1`
    #   V34 V35 V36 V37 V38
    # 1  44   N   6   E  11
    # 2  44   N   6   E  11
    ### truncated for brevity
    

    Таким образом, мы используем sapply, чтобы сделать что-то для каждого из этих кадров, возвращая его (в данном случае) упрощенно.(Если мы укажем simplify=FALSE или если не все они имеют одинаковую длину, он будет возвращен без упрощения, как list вместо vector).

  • Функция, которую мы применяем к каждому кадру, - это apply(., 1, paste0, collapse0), которая будет возвращать вектор вставок из 5 столбцов, что-то вроде:

    apply(s, 1, paste0, collapse = "")
    # $`0`
    # [1] ""044N005E026" "044N005E026""
    

    Поскольку мы хотим, чтобы они были объединены, мы окружаем его как paste(apply(...), collapse = "-").

...