Разделить значение по умолчанию без сортировки по именам столбцов

#r #dataframe

#r #фрейм данных

Вопрос:

Для следующих данных, которые я использую split.default() в R . Проблема в том, что разделенные подразделы data.frames() в списке сортируются на основе имени столбца.

Я не хочу, чтобы это происходило, и хочу сохранить последовательность имен столбцов, поскольку это исходные данные. Есть ли подход, которому я могу следовать, чтобы сделать это? Пожалуйста, предложите.

Входные данные

 data <- structure(list(`B-DIODE` = c(1.2, 0.4), `B-DIODE` = c(1.3, 0.6
), `A-DIODE` = c(1.4, 0.8), `A-ACC1` = c(1.5, 1), `A-ACC2` = c(1.6, 
1.2), `A-ANA0` = c(1.7, 1.4), `A-ANA1` = c(1.8, 1.6), `A-BRICKID` = c(1.9, 
1.8), `A-CC0` = c(2L, 2L), `A-CC1` = c(2.1, 2.2), `A-DIGDN` = c(2.2, 
2.4), `A-DIGDP` = c(2.3, 2.6), `A-DN1` = c(2.4, 2.8), `A-DN2` = c(2.5, 
3), `A-DP1` = c(2.6, 3.2), `A-DP2` = c(2.7, 3.4), `A-SCL` = c(2.8, 
3.6), `A-SDA` = c(2.9, 3.8), `A-USB0DN` = 3:4, `A-USB0DP` = c(3.1, 
4.2), `A-USB1DN` = c(3.2, 4.4), `A-USB1DP` = c(3.3, 4.6), `A-ACC1` = c(3.4, 
4.8), `A-ACC2` = c(3.5, 5), `A-ANA0` = c(3.6, 5.2), `A-ANA1` = c(3.7, 
5.4), `A-BRICKID` = c(3.8, 5.6), `A-CC0` = c(3.9, 5.8), `A-CC1` = c(4L, 
6L), `A-DIGDN` = c(4.1, 6.2), `A-DIGDP` = c(4.2, 6.4), `A-DN1` = c(4.3, 
6.6), `A-DN2` = c(4.4, 6.8), `A-DP1` = c(4.5, 7), `A-DP2` = c(4.6, 
7.2), `A-SCL` = c(4.7, 7.4), `A-SDA` = c(4.8, 7.6), `A-USB0DN` = c(4.9, 
7.8), `A-USB0DP` = c(5L, 8L), `A-USB1DN` = c(5.1, 8.2), `A-USB1DP` = c(5.2, 
8.4), `A-NA` = c(5.3, 8.6), `A-ACC2PWRLKG_0v4` = c(5.4, 8.8), 
`A-ACC2PWRLKG_0v4` = c(5.5, 9), `A-P_IN_Leak` = c(5.6, 9.2
)), class = "data.frame", row.names = c(NA, -2L))
  

Код

 split.default(data, sub("-.*", "", names(data)))
  

Вывод

 $`A`
  A-DIODE A-ACC1 A-ACC2 A-ANA0 A-ANA1 A-BRICKID A-CC0 A-CC1 A-DIGDN A-DIGDP A-DN1 A-DN2 A-DP1 A-DP2 A-SCL A-SDA A-USB0DN A-USB0DP A-USB1DN A-USB1DP
1     1.4    1.5    1.6    1.7    1.8       1.9     2   2.1     2.2     2.3   2.4   2.5   2.6   2.7   2.8   2.9        3      3.1      3.2      3.3
2     0.8    1.0    1.2    1.4    1.6       1.8     2   2.2     2.4     2.6   2.8   3.0   3.2   3.4   3.6   3.8        4      4.2      4.4      4.6
  A-ACC1.1 A-ACC2.1 A-ANA0.1 A-ANA1.1 A-BRICKID.1 A-CC0.1 A-CC1.1 A-DIGDN.1 A-DIGDP.1 A-DN1.1 A-DN2.1 A-DP1.1 A-DP2.1 A-SCL.1 A-SDA.1 A-USB0DN.1
1      3.4      3.5      3.6      3.7         3.8     3.9       4       4.1       4.2     4.3     4.4     4.5     4.6     4.7     4.8        4.9
2      4.8      5.0      5.2      5.4         5.6     5.8       6       6.2       6.4     6.6     6.8     7.0     7.2     7.4     7.6        7.8
  A-USB0DP.1 A-USB1DN.1 A-USB1DP.1 A-NA A-ACC2PWRLKG_0v4 A-ACC2PWRLKG_0v4.1 A-P_IN_Leak
1          5        5.1        5.2  5.3              5.4                5.5         5.6
2          8        8.2        8.4  8.6              8.8                9.0         9.2

$B
  B-DIODE B-DIODE.1
1     1.2       1.3
2     0.4       0.6

  

В приведенном выше выводе я хочу, чтобы $B сначала отображался, а затем $A , поскольку это последовательность, которая Input Data следовала.

Ответ №1:

Один из вариантов — преобразовать имена в factor и установить уровни по мере необходимости

 new_name <- sub("-.*", "", names(data))
split.default(data, factor(new_name, levels = unique(new_name)))

#$B
#  B-DIODE B-DIODE.1
#1     1.2       1.3
#2     0.4       0.6

#$A
#  A-DIODE A-ACC1 A-ACC2 A-ANA0 ....
#1     1.4    1.5    1.6    1.7 ....   
#2     0.8    1.0    1.2    1.4 ....   
  

указав levels as unique(new_name) , мы можем гарантировать, что список будет разделен на основе их появления во фрейме данных, а не в алфавитном порядке.

Как предлагает @thelatemail, мы также можем избежать преобразования имен в factor переменную, изменив порядок списка на основе unique new_name

 split.default(data, new_name)[unique(new_name)]
  

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

1. factor Преобразование не должно быть необходимым, поскольку я почти уверен, что unique выполняется в порядке появления, поэтому split.default(data, new_name)[unique(new_name)] должно быть достаточно.

Ответ №2:

Другим вариантом является создание групповых индексов для разделения с помощью rle

 rl <- rle(sub("-.*", "", names(data)))
split.default(data, rep(1:length(rl), rl$length))
#$`1`
#  B-DIODE B-DIODE.1
#1     1.2       1.3
#2     0.4       0.6
#
#$`2`
#  A-DIODE A-ACC1 A-ACC2 A-ANA0 A-ANA1 A-BRICKID A-CC0 A-CC1 A-DIGDN A-DIGDP
#1     1.4    1.5    1.6    1.7    1.8       1.9     2   2.1     2.2     2.3
#2     0.8    1.0    1.2    1.4    1.6       1.8     2   2.2     2.4     2.6
#  A-DN1 A-DN2 A-DP1 A-DP2 A-SCL A-SDA A-USB0DN A-USB0DP A-USB1DN A-USB1DP
#1   2.4   2.5   2.6   2.7   2.8   2.9        3      3.1      3.2      3.3
#2   2.8   3.0   3.2   3.4   3.6   3.8        4      4.2      4.4      4.6
#  A-ACC1.1 A-ACC2.1 A-ANA0.1 A-ANA1.1 A-BRICKID.1 A-CC0.1 A-CC1.1 A-DIGDN.1
#1      3.4      3.5      3.6      3.7         3.8     3.9       4       4.1
#2      4.8      5.0      5.2      5.4         5.6     5.8       6       6.2
#  A-DIGDP.1 A-DN1.1 A-DN2.1 A-DP1.1 A-DP2.1 A-SCL.1 A-SDA.1 A-USB0DN.1
#1       4.2     4.3     4.4     4.5     4.6     4.7     4.8        4.9
#2       6.4     6.6     6.8     7.0     7.2     7.4     7.6        7.8
#  A-USB0DP.1 A-USB1DN.1 A-USB1DP.1 A-NA A-ACC2PWRLKG_0v4 A-ACC2PWRLKG_0v4.1
#1          5        5.1        5.2  5.3              5.4                5.5
#2          8        8.2        8.4  8.6              8.8                9.0
#  A-P_IN_Leak
#1         5.6
#2         9.2