从单个 table 中查找多列
Lookup multiple column from a single table
假设我有以下数据
df <- structure(list(car_model = c(301, 302, 303, 304), colour = c(501,
502, 503, 504), sales = c(182, 191, 302, 101)), row.names = c(NA,
-4L), class = c("tbl_df", "tbl", "data.frame"))
我有一个查找 table,我将在其中获取文本以替换列 car_model
和 colour
.
中的代码
tbl1 <- structure(list(txt = c("A", "B", "C", "Y"), cod = c(301, 302,
303, 304), var = c("car_model", "car_model", "car_model", "car_model"
)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"
))
tbl2 <- structure(list(txt = c("black", "green", "red", "white"), cod = c(501,
502, 503, 504), var = c("colour", "colour", "colour", "colour"
)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"
))
结合我拥有的两个 table
tbl <- rbind(tbl1,tbl2)
# A tibble: 8 x 3
txt cod var
<chr> <dbl> <chr>
1 A 301 car_model
2 B 302 car_model
3 C 303 car_model
4 Y 304 car_model
5 black 501 colour
6 green 502 colour
7 red 503 colour
8 white 504 colour
有没有一种方法可以使用这种查找 table 来替换主 df
中的所有列(通过列 var
和 [ 中的值匹配列名=18=]) 或者我需要制作单独的 tables,每个变量一个?我的另一个疑问是,在具有约 1000 万行、30 个或更多变量和总大小约 5000 行的查找 table 的数据集中执行此操作是否合理。
编辑:关于代码可以在不同的变量中使用相同的代码。
EDIT2:我正在寻找一种快速且内存高效的解决方案。也许 data.table
的一些解决方案
这是 tidyverse
的一种方式
- 循环
across
在 'tbl' 的 'var' 列的 unique
值中找到的列
- 获取带
cur_column()
的循环列的列名,在'tbl'的'var'列上创建逻辑表达式('i1')
- 使用
match
获取列值与'tbl' 的'cod'列的子集匹配的位置索引
- 根据'i1'
从子集中提取'tbl'对应的'txt'列
library(dplyr)
df <- df %>%
mutate(across(all_of(unique(tbl$var)),
~ {i1 <- tbl$var == cur_column()
tbl$txt[i1][match(., tbl$cod[i1])]}))
-输出
df
# A tibble: 4 x 3
car_model colour sales
<chr> <chr> <dbl>
1 A black 182
2 B green 191
3 C red 302
4 Y white 101
或者用data.table
,我们可以用同样的方法
- 从 'tbl' ('nm1')
创建了一个命名向量
- 将 'data.frame' 转换为 'data.table' (
setDT
)
- 从 'var'
的 unique
元素指定 .SDcols
中感兴趣的列
- 通过
Map
循环执行 match
并将输出分配 (:=
) 回原始列
library(data.table)
nm1 <- setNames(tbl$txt, tbl$cod)
un1 <- unique(tbl$var)
setDT(df)[, (un1) := Map(function(x, y)
nm1[tbl$var == y][as.character(x)], .SD, un1), .SDcols = un1]
-输出
df
car_model colour sales
1: A black 182
2: B green 191
3: C red 302
4: Y white 101
或者可以使用base R
lst1 <- with(tbl, split(setNames(txt, cod), var))
df[un1] <- Map(function(x, y) y[as.character(x)], df[un1], lst1)
一个data.table
选项
cbind(unstack(setDT(tbl)[melt(
setDT(df)[, .(car_model, colour)], ,
variable.name = "var",
value.name = "cod"
), .(txt, var), on = .(var, cod)]), df[, .(sales)])
给予
car_model colour sales
1 A black 182
2 B green 191
3 C red 302
4 Y white 101
您可以重塑数据并执行连接。
library(dplyr)
library(tidyr)
df %>%
pivot_longer(cols = -sales) %>%
left_join(tbl, by = c('name' = 'var', 'value' = 'cod')) %>%
select(-value) %>%
pivot_wider(names_from = name, values_from = txt)
# sales car_model colour
# <dbl> <chr> <chr>
#1 182 A black
#2 191 B green
#3 302 C red
#4 101 Y white
假设我有以下数据
df <- structure(list(car_model = c(301, 302, 303, 304), colour = c(501,
502, 503, 504), sales = c(182, 191, 302, 101)), row.names = c(NA,
-4L), class = c("tbl_df", "tbl", "data.frame"))
我有一个查找 table,我将在其中获取文本以替换列 car_model
和 colour
.
tbl1 <- structure(list(txt = c("A", "B", "C", "Y"), cod = c(301, 302,
303, 304), var = c("car_model", "car_model", "car_model", "car_model"
)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"
))
tbl2 <- structure(list(txt = c("black", "green", "red", "white"), cod = c(501,
502, 503, 504), var = c("colour", "colour", "colour", "colour"
)), row.names = c(NA, -4L), class = c("tbl_df", "tbl", "data.frame"
))
结合我拥有的两个 table
tbl <- rbind(tbl1,tbl2)
# A tibble: 8 x 3
txt cod var
<chr> <dbl> <chr>
1 A 301 car_model
2 B 302 car_model
3 C 303 car_model
4 Y 304 car_model
5 black 501 colour
6 green 502 colour
7 red 503 colour
8 white 504 colour
有没有一种方法可以使用这种查找 table 来替换主 df
中的所有列(通过列 var
和 [ 中的值匹配列名=18=]) 或者我需要制作单独的 tables,每个变量一个?我的另一个疑问是,在具有约 1000 万行、30 个或更多变量和总大小约 5000 行的查找 table 的数据集中执行此操作是否合理。
编辑:关于代码可以在不同的变量中使用相同的代码。
EDIT2:我正在寻找一种快速且内存高效的解决方案。也许 data.table
这是 tidyverse
- 循环
across
在 'tbl' 的 'var' 列的 - 获取带
cur_column()
的循环列的列名,在'tbl'的'var'列上创建逻辑表达式('i1') - 使用
match
获取列值与'tbl' 的'cod'列的子集匹配的位置索引
- 根据'i1' 从子集中提取'tbl'对应的'txt'列
unique
值中找到的列
library(dplyr)
df <- df %>%
mutate(across(all_of(unique(tbl$var)),
~ {i1 <- tbl$var == cur_column()
tbl$txt[i1][match(., tbl$cod[i1])]}))
-输出
df
# A tibble: 4 x 3
car_model colour sales
<chr> <chr> <dbl>
1 A black 182
2 B green 191
3 C red 302
4 Y white 101
或者用data.table
,我们可以用同样的方法
- 从 'tbl' ('nm1') 创建了一个命名向量
- 将 'data.frame' 转换为 'data.table' (
setDT
) - 从 'var' 的
- 通过
Map
循环执行match
并将输出分配 (:=
) 回原始列
unique
元素指定 .SDcols
中感兴趣的列
library(data.table)
nm1 <- setNames(tbl$txt, tbl$cod)
un1 <- unique(tbl$var)
setDT(df)[, (un1) := Map(function(x, y)
nm1[tbl$var == y][as.character(x)], .SD, un1), .SDcols = un1]
-输出
df
car_model colour sales
1: A black 182
2: B green 191
3: C red 302
4: Y white 101
或者可以使用base R
lst1 <- with(tbl, split(setNames(txt, cod), var))
df[un1] <- Map(function(x, y) y[as.character(x)], df[un1], lst1)
一个data.table
选项
cbind(unstack(setDT(tbl)[melt(
setDT(df)[, .(car_model, colour)], ,
variable.name = "var",
value.name = "cod"
), .(txt, var), on = .(var, cod)]), df[, .(sales)])
给予
car_model colour sales
1 A black 182
2 B green 191
3 C red 302
4 Y white 101
您可以重塑数据并执行连接。
library(dplyr)
library(tidyr)
df %>%
pivot_longer(cols = -sales) %>%
left_join(tbl, by = c('name' = 'var', 'value' = 'cod')) %>%
select(-value) %>%
pivot_wider(names_from = name, values_from = txt)
# sales car_model colour
# <dbl> <chr> <chr>
#1 182 A black
#2 191 B green
#3 302 C red
#4 101 Y white