Объединить пары переменных с одинаковым суффиксом - PullRequest
0 голосов
/ 30 декабря 2018

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

first.1 second.1 first.2 second.2 
1222 3223 3333 1221 
1111 2212 2232 2113 

Вот как я делаю это неэффективно без цикла for:

df$concatenated.1 <- paste0(df$first.1,"-",df$second.1)
df$concatenated.2 <- paste0(df$first.2,"-",df$second.2)

Какие результатыв следующем фрейме данных df :

first.1 second.1 first.2 second.2 concatenated.1 concatenated.2 
1222 3223 3333 1221 1222-3223 3333-1221 
1111 2212 2232 2113 1111-2212 2232-2113 

У меня есть более 2 пар переменных для объединения, поэтому я хотел бы сделать это в цикле for:

for (i in 1:2){
??
}

Есть идеи, как этого добиться?

Ответы [ 5 ]

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

вы можете использовать функцию stri_join в пакете stringi, что очень быстро.

library(data.table)
library(stringi)

df <- fread("first.1 second.1 first.2 second.2 
             1222 3223 3333 1221 
             1111 2212 2232 2113")

cols <- paste0("concatenated_", 1:2)
df[, (cols) := Map(stri_join, .(first.1, first.2), .(second.1, second.2), sep = "-")]
setDF(df)

first.1 second.1 first.2 second.2 concatenated_1 concatenated_2
1    1222     3223    3333     1221      1222-3223      3333-1221
2    1111     2212    2232     2113      1111-2212      2232-2113
0 голосов
/ 30 декабря 2018

library(tidyverse)

[РЕДАКТИРОВАНИЕ: неправильное использование исходного решения starts_with]

В этом решении для выбора соответствующих столбцов используется ends_with(), а затем unite для объединения их с- разделитель:

df <- tribble(
        ~first.1, ~second.1, ~first.2, ~second.2,
        1222,3223,3333,1221,
        1111,2212,2232,2113)

df1 <- df %>%
  select(ends_with("1")) %>%
  unite(concatenated.1, sep = "-")

df2 <- df %>%
  select(ends_with("2")) %>%
  unite(concatenated.2, sep = "-")

cbind(df, df1, df2)
0 голосов
/ 30 декабря 2018

Если бы вы могли найти способ разбить столбцы, это было бы намного проще.Например, на основе предоставленного примера мы можем разделить столбцы по последним символам имен столбцов (1, 1, 2, 2).

Используя базу R, мы используем split.default, чтобы разделить столбцы по именам (как описано выше), а для каждой группы мы paste каждой строки и добавляем новые столбцы.

group_names <- substring(names(df), nchar(names(df)))
df[paste0("concatenated.", unique(group_names))] <- 
     lapply(split.default(df,group_names),  function(x)  do.call(paste, c(x, sep = "-")))

df
#  first.1 second.1 first.2 second.2 concatenated.1 concatenated.2
#1    1222     3223    3333     1221      1222-3223      3333-1221
#2    1111     2212    2232     2113      1111-2212      2232-2113
0 голосов
/ 30 декабря 2018

Если ваши реальные данные имеют имена, которые следуют четкой схеме, как в данных этого примера, ответ Ронака split / lapply, вероятно, будет лучшим.Если нет, вы можете просто создать векторы имен и использовать Map с paste.

new.names <- paste0('concatenated.', 1:2)
names.1 <- paste0('first.', 1:2)
names.2 <- paste0('second.', 1:2)

df[new.names] <- Map(paste, df[names.1], df[names.2], sep = '-')

df

#   first.1 second.1 first.2 second.2 concatenated.1 concatenated.2
# 1    1222     3223    3333     1221      1222-3223      3333-1221
# 2    1111     2212    2232     2113      1111-2212      2232-2113
0 голосов
/ 30 декабря 2018

Вот решение tidyverse , которое поможет вам в этом.Единственное отличие состоит в том, что столбцы выводятся в алфавитном порядке, то есть «первые», затем «сцепленные», затем «секунды».

txt <- 'first.1 second.1 first.2 second.2 
1222 3223 3333 1221 
1111 2212 2232 2113'

df <- read.table(text = txt, header = T)

library(tidyverse)

df2 <- df %>% 
  mutate(row.num = row_number()) %>% 
  gather(variable, value, -row.num) %>% 
  separate(variable, into = c('order', 'pair')) %>% 
  spread(order, value) %>% 
  mutate(concatenated = paste0(first, '-', second)) %>% 
  gather(variable, value, -row.num, -pair) %>% 
  unite(name, variable, pair) %>% 
  spread(name, value)

  row.num concatenated_1 concatenated_2 first_1 first_2 second_1 second_2
1       1      1222-3223      3333-1221    1222    3333     3223     1221
2       2      1111-2212      2232-2113    1111    2232     2212     2113
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...