我目前有一个 Excel 文档,简化后如下所示:
A1 A2 B1 B2 B3 C1 C2 ... H12
1 5 11 14 15 19 22 ... ...
2 6 12 16 20 23
3 7 13 17 21 24
4 8 18 25
9 26
10 27
我必须以两种不同的方式组合列以获得两个不同的结果文档。 首先,我必须以将所有仅包含数字 1 的列组合在一起的方式组合列,这将产生如下所示的文档:
Column 1 Column 2 Column 3 ... Column 12
1 5 15 ... ...
2 6 16
3 7 17
4 8 18
11 9
12 10
13 14
19 22
20 23
21 24
25
26
27
对于第二种方式,我需要以一种将所有以相同数字开头的原始列合并为一列的方式来组合列,例如:
Column A Column B Column C ... Column H
1 11 19 ... ...
2 12 20
3 13 21
4 14 22
5 15 23
6 16 24
7 17 25
8 18 26
9 27
10
要转换的文件的标头编号为从 A1 到 H12。这意味着第一个生成的文档最终应有 12 列,第二个文档应有 8 列。
我已经尝试过用
rbind
这样做,但我没能做到。
有人可以帮我解决这个问题吗?
提前非常感谢您!
听起来您阅读 Excel 没有问题,所以我假设您只是将整个工作表读入 data.frame
table
。您可以使用 tidyr::pivot_longer
获取数据框,其中一个条目中存在对行标题的引用,而另一个条目中存在对值的引用:
table <- pivot_longer(table, cols = names(table), values_drop_na = TRUE)
然后您可以使用
substring
创建两个带有数字和字母的附加列:
table$number <- substring(table$name, 2)
table$letter <- substring(table$name, 1, 1)
写可以分两个for循环完成:(我用
openxlsx
)
byNumbers <- buildWorkbook("")
for(i in 1:12){
vec <- c(i, filter(table, number == i)$value)
writeData(wb = byNumbers, sheet = 1, x = vec, startCol = i)
}
byLetter <- buildWorkbook("")
for(i in 1:8){ # H is the 8th letter
iLet <- LETTERS[i]
vec <- c(iLet, filter(table, letter == iLet)$value)
writeData(wb = byLetter, sheet = 1, x = vec, startCol = i)
}
然后您可以保存两个工作簿。
希望这有帮助!
肯定有更优雅的方法,但是如果不知道标题或数据在现实中是什么样子,这将是一个相对没有魔法的路径:
library(tidyverse)
# Put data.frame into long format
df_long <- df %>%
# Put data into long format
gather(key, val) %>% #you could also use pivot_longer()
drop_na() %>%
# Separate letters and numbers
separate(key, c("letter", "number"), sep = "(?=[0-9]{1,2}$)") %>%
# Sort
arrange(letter, number)
# Result
> head(df_long)
letter number val
1 A 1 1
2 A 1 2
3 A 1 3
4 A 1 4
5 A 2 5
6 A 2 6
...
# By letters
df_letters <- df_long %>%
# Drop number col
select(-number) %>%
# Add rolling ID
group_by(letter) %>%
mutate(id = row_number()) %>%
ungroup() %>%
# Spread into wide format
pivot_wider(
id_cols = id, names_from = letter, names_prefix = "Column_", values_from = val
) %>%
select(-id)
# Result
df_letters
# A tibble: 10 × 3
Column_A Column_B Column_C
<int> <int> <int>
1 1 11 19
2 2 12 20
3 3 13 21
4 4 14 22
5 5 15 23
6 6 16 24
7 7 17 25
8 8 18 26
9 9 NA 27
10 10 NA NA
# By numbers
df_numbers <- df_long %>%
# Drop letter col
select(-letter) %>%
# Add rolling ID
group_by(number) %>%
mutate(id = row_number()) %>%
ungroup() %>%
# Spread into wide format
pivot_wider(
id_cols = id, names_from = number, names_prefix = "Column_", values_from = val
) %>%
# Drop ID col
select(-id)
# Result
> df_numbers
# A tibble: 13 × 3
Column_1 Column_2 Column_3
<int> <int> <int>
1 1 5 15
2 2 6 16
3 3 7 17
4 4 8 18
5 11 9 NA
6 12 10 NA
7 13 14 NA
8 19 22 NA
9 20 23 NA
10 21 24 NA
11 NA 25 NA
12 NA 26 NA
13 NA 27 NA
df <- structure(list(A1=c(1L,2L,3L,4L,NA,NA),A2=5:10,B1=c(11L,12L,13L,NA,NA,NA),B2=c(14L,NA,NA,NA,NA,NA),B3=c(15L,16L,17L,18L,NA,NA),C1=c(19L,20L,21L,NA,NA,NA),C2=22:27),row.names=c(NA,-6L),class=c("data.table","data.frame"))