使用另一列 R 中的值通过 str_split 处理数据框列
Processing dataframe column via str_split using values in another column R
我想知道是否有更好的方法来解决以下问题
我有一个具有以下示例结构的数据框:
Split_key
label
sub_label
A_B_C
7
""
A_B_C
7
""
A_B_C
8
""
A_B_C
8
""
A_B_C
10
""
A_B_C
10
""
D_E_F
2
""
D_E_F
7
""
D_E_F
15
""
G_H_I
1
""
G_H_I
2
""
G_H_I
3
""
我希望用一个值填充 sub_label,该值对应于在“_”字符上拆分 Split_key 中的值,并根据标签获取正确的元素。正确的元素是在 Split_key.
中共享相同值的唯一排序标签数组中标签中值的索引
此处显示了正确的最终结果。
Split_key
label
sub_label
A_B_C
7
A
A_B_C
7
A
A_B_C
8
B
A_B_C
8
B
A_B_C
10
C
A_B_C
10
C
D_E_F
2
D
D_E_F
7
E
D_E_F
15
F
G_H_I
1
G
G_H_I
2
H
G_H_I
3
I
这是我的初步尝试。
for (row_n in 1:nrow(df)){
df%>%filter(`Split_key`==df[row_n,"Split_key"][[1]])->duplicates
shift<-which(sort(unique(duplicates$label))==df[row_n,"label"][[1]])
df[row_n,"sub_label"]<-str_split(df[row_n,"Split_key"],"_")[[1]][shift]
}
此解决方案有效,但比我希望的大型数据帧慢。有没有不使用 for 循环来完成这个任务的方法?
这将比循环更快:
library(dplyr)
dat %>%
group_by(Split_key) %>%
mutate(sub_label2 = strsplit(Split_key[1], "_")[[1]][ match(label, sort(unique(label))) ]) %>%
ungroup()
# # A tibble: 12 x 4
# Split_key label sub_label sub_label2
# <chr> <int> <chr> <chr>
# 1 A_B_C 7 A A
# 2 A_B_C 7 A A
# 3 A_B_C 8 B B
# 4 A_B_C 8 B B
# 5 A_B_C 10 C C
# 6 A_B_C 10 C C
# 7 D_E_F 2 D D
# 8 D_E_F 7 E E
# 9 D_E_F 15 F F
# 10 G_H_I 1 G G
# 11 G_H_I 2 H H
# 12 G_H_I 3 I I
如果 Split_key
中编码的元素少于 sub_label
中的不同值,那么这些行将得到 NA
。
演练:
group_by(Split_key)
:因为我们需要为每个Split_key
跟踪唯一的label
,所以我们在这个字段进行分组,一次简化为一组处理;
strsplit(Split_key[1], ")")[[1]]
:在一个特定的组中,我们只需要拆分 Split_key
个值中的一个,而不是所有的值(因为它们都是相同的),这在内部产生了一个向量这样作为第一组中的 c("A", "B", "C")
;
match(label, sort(unique(label)))
将(第一组)翻译成 match(c(7,7,8,8,10,10), c(7,8,10))
,然后翻译成 c(1,1,2,2,3,3)
;这用于索引上一个项目符号 的向量 c("A","B","C")
这是实现目标的另一种方法:
逻辑:
- 分组
Split_key
- 使用
data.table
中的 rleid
函数为 label
创建分组变量
- 使用一些 stringr 函数来达到目标:
library(dplyr)
library(stringr)
library(data.table)
df %>%
group_by(Split_key) %>%
mutate(group = rleid(label)) %>%
mutate(sub_label= str_sub(str_replace_all(Split_key, "[^[:alnum:]]", ""), group, group), .keep="unused")
Split_key label sub_label
<chr> <int> <chr>
1 A_B_C 7 A
2 A_B_C 7 A
3 A_B_C 8 B
4 A_B_C 8 B
5 A_B_C 10 C
6 A_B_C 10 C
7 D_E_F 2 D
8 D_E_F 7 E
9 D_E_F 15 F
10 G_H_I 1 G
11 G_H_I 2 H
12 G_H_I 3 I
我们可以使用 factor
路由,即在按 'Split_key' 分组后,scan
'Split_key' 的 first
元素并使用 integer
将 factor
列 'label' 转换为索引
library(dplyr)
df %>%
group_by(Split_key) %>%
mutate(sub_label = scan(text = first(Split_key), what = "",
sep="_", quiet = TRUE)[as.integer(factor(label))]) %>%
ungroup
-输出
# A tibble: 12 × 3
Split_key label sub_label
<chr> <int> <chr>
1 A_B_C 7 A
2 A_B_C 7 A
3 A_B_C 8 B
4 A_B_C 8 B
5 A_B_C 10 C
6 A_B_C 10 C
7 D_E_F 2 D
8 D_E_F 7 E
9 D_E_F 15 F
10 G_H_I 1 G
11 G_H_I 2 H
12 G_H_I 3 I
数据
df <- structure(list(Split_key = c("A_B_C", "A_B_C", "A_B_C", "A_B_C",
"A_B_C", "A_B_C", "D_E_F", "D_E_F", "D_E_F", "G_H_I", "G_H_I",
"G_H_I"), label = c(7L, 7L, 8L, 8L, 10L, 10L, 2L, 7L, 15L, 1L,
2L, 3L), sub_label = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA)), class = "data.frame", row.names = c(NA, -12L))
我想知道是否有更好的方法来解决以下问题
我有一个具有以下示例结构的数据框:
Split_key | label | sub_label |
---|---|---|
A_B_C | 7 | "" |
A_B_C | 7 | "" |
A_B_C | 8 | "" |
A_B_C | 8 | "" |
A_B_C | 10 | "" |
A_B_C | 10 | "" |
D_E_F | 2 | "" |
D_E_F | 7 | "" |
D_E_F | 15 | "" |
G_H_I | 1 | "" |
G_H_I | 2 | "" |
G_H_I | 3 | "" |
我希望用一个值填充 sub_label,该值对应于在“_”字符上拆分 Split_key 中的值,并根据标签获取正确的元素。正确的元素是在 Split_key.
中共享相同值的唯一排序标签数组中标签中值的索引此处显示了正确的最终结果。
Split_key | label | sub_label |
---|---|---|
A_B_C | 7 | A |
A_B_C | 7 | A |
A_B_C | 8 | B |
A_B_C | 8 | B |
A_B_C | 10 | C |
A_B_C | 10 | C |
D_E_F | 2 | D |
D_E_F | 7 | E |
D_E_F | 15 | F |
G_H_I | 1 | G |
G_H_I | 2 | H |
G_H_I | 3 | I |
这是我的初步尝试。
for (row_n in 1:nrow(df)){
df%>%filter(`Split_key`==df[row_n,"Split_key"][[1]])->duplicates
shift<-which(sort(unique(duplicates$label))==df[row_n,"label"][[1]])
df[row_n,"sub_label"]<-str_split(df[row_n,"Split_key"],"_")[[1]][shift]
}
此解决方案有效,但比我希望的大型数据帧慢。有没有不使用 for 循环来完成这个任务的方法?
这将比循环更快:
library(dplyr)
dat %>%
group_by(Split_key) %>%
mutate(sub_label2 = strsplit(Split_key[1], "_")[[1]][ match(label, sort(unique(label))) ]) %>%
ungroup()
# # A tibble: 12 x 4
# Split_key label sub_label sub_label2
# <chr> <int> <chr> <chr>
# 1 A_B_C 7 A A
# 2 A_B_C 7 A A
# 3 A_B_C 8 B B
# 4 A_B_C 8 B B
# 5 A_B_C 10 C C
# 6 A_B_C 10 C C
# 7 D_E_F 2 D D
# 8 D_E_F 7 E E
# 9 D_E_F 15 F F
# 10 G_H_I 1 G G
# 11 G_H_I 2 H H
# 12 G_H_I 3 I I
如果 Split_key
中编码的元素少于 sub_label
中的不同值,那么这些行将得到 NA
。
演练:
group_by(Split_key)
:因为我们需要为每个Split_key
跟踪唯一的label
,所以我们在这个字段进行分组,一次简化为一组处理;strsplit(Split_key[1], ")")[[1]]
:在一个特定的组中,我们只需要拆分Split_key
个值中的一个,而不是所有的值(因为它们都是相同的),这在内部产生了一个向量这样作为第一组中的c("A", "B", "C")
;match(label, sort(unique(label)))
将(第一组)翻译成match(c(7,7,8,8,10,10), c(7,8,10))
,然后翻译成c(1,1,2,2,3,3)
;这用于索引上一个项目符号 的向量
c("A","B","C")
这是实现目标的另一种方法: 逻辑:
- 分组
Split_key
- 使用
data.table
中的 - 使用一些 stringr 函数来达到目标:
rleid
函数为 label
创建分组变量
library(dplyr)
library(stringr)
library(data.table)
df %>%
group_by(Split_key) %>%
mutate(group = rleid(label)) %>%
mutate(sub_label= str_sub(str_replace_all(Split_key, "[^[:alnum:]]", ""), group, group), .keep="unused")
Split_key label sub_label
<chr> <int> <chr>
1 A_B_C 7 A
2 A_B_C 7 A
3 A_B_C 8 B
4 A_B_C 8 B
5 A_B_C 10 C
6 A_B_C 10 C
7 D_E_F 2 D
8 D_E_F 7 E
9 D_E_F 15 F
10 G_H_I 1 G
11 G_H_I 2 H
12 G_H_I 3 I
我们可以使用 factor
路由,即在按 'Split_key' 分组后,scan
'Split_key' 的 first
元素并使用 integer
将 factor
列 'label' 转换为索引
library(dplyr)
df %>%
group_by(Split_key) %>%
mutate(sub_label = scan(text = first(Split_key), what = "",
sep="_", quiet = TRUE)[as.integer(factor(label))]) %>%
ungroup
-输出
# A tibble: 12 × 3
Split_key label sub_label
<chr> <int> <chr>
1 A_B_C 7 A
2 A_B_C 7 A
3 A_B_C 8 B
4 A_B_C 8 B
5 A_B_C 10 C
6 A_B_C 10 C
7 D_E_F 2 D
8 D_E_F 7 E
9 D_E_F 15 F
10 G_H_I 1 G
11 G_H_I 2 H
12 G_H_I 3 I
数据
df <- structure(list(Split_key = c("A_B_C", "A_B_C", "A_B_C", "A_B_C",
"A_B_C", "A_B_C", "D_E_F", "D_E_F", "D_E_F", "G_H_I", "G_H_I",
"G_H_I"), label = c(7L, 7L, 8L, 8L, 10L, 10L, 2L, 7L, 15L, 1L,
2L, 3L), sub_label = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA)), class = "data.frame", row.names = c(NA, -12L))