R 元素到元素的操作在组中的几列
R Element-to-Element operations on several columns in groups
我们有 mtcars
数据集,想要计算一组不同汽车之间的函数,将几列作为输入。
更具体地说:
- 按变速箱
am
和齿轮 gear
分组
- 比较同一组中的所有汽车(car1 到 car2、car1 到 car3、car2 到 car3...)
- 第一辆车的排量是否比第二辆车大?
disp1>disp2
- 并且第一辆车的马力是否比第二辆车大?
hp1>hp2
结果应如下所示:
# Car1 Car2 result
# Mazda RX4 Mazda RX4 Wag false
# Mazda RX4 Datsun 710 false
# Mazda RX4 Wag Datsun 710 true
在中是按组进行外层操作,但只用到了单列。是否可以将其扩展到多个列?如果可能的话,最好在结果 table.
中包含 disp1
、disp2
等列
这有点乱,但您可以执行以下操作:
library(dplyr)
library(tidyr)
dat <- mtcars %>%
tibble::rownames_to_column(var = "Car1") %>%
mutate(Car2 = Car1) %>%
group_by(am, gear) %>%
expand(Car1, Car2) %>%
left_join(tibble::rownames_to_column(mtcars, var = "Car1"), by = "Car1") %>%
left_join(tibble::rownames_to_column(mtcars, var = "Car2"), by = "Car2") %>%
ungroup() %>%
mutate(result = disp.x > disp.y & hp.x > hp.y) %>%
select(Car1, Car2, result)
然后我们得到了预期的结果:
dat
# A tibble: 330 x 3
Car1 Car2 result
<chr> <chr> <lgl>
1 AMC Javelin AMC Javelin FALSE
2 AMC Javelin Cadillac Fleetwood FALSE
3 AMC Javelin Camaro Z28 FALSE
4 AMC Javelin Chrysler Imperial FALSE
5 AMC Javelin Dodge Challenger FALSE
6 AMC Javelin Duster 360 FALSE
7 AMC Javelin Hornet 4 Drive TRUE
8 AMC Javelin Hornet Sportabout FALSE
9 AMC Javelin Lincoln Continental FALSE
10 AMC Javelin Merc 450SE FALSE
# … with 320 more rows
dat %>% filter(Car1 == "Mazda RX4")
# A tibble: 8 x 3
Car1 Car2 result
<chr> <chr> <lgl>
1 Mazda RX4 Datsun 710 TRUE
2 Mazda RX4 Fiat 128 TRUE
3 Mazda RX4 Fiat X1-9 TRUE
4 Mazda RX4 Honda Civic TRUE
5 Mazda RX4 Mazda RX4 FALSE
6 Mazda RX4 Mazda RX4 Wag FALSE
7 Mazda RX4 Toyota Corolla TRUE
8 Mazda RX4 Volvo 142E TRUE
(虽然马自达 RX4 与 Datsun 710 的比较与您陈述的预期结果不同,但实际上是正确的:)
mtcars %>%
tibble::rownames_to_column(var = "Car1") %>%
filter(Car1 %in% c("Mazda RX4", "Datsun 710"))
Car1 mpg cyl disp hp drat wt qsec vs am gear carb
1 Mazda RX4 21.0 6 160 110 3.90 2.62 16.46 0 1 4 4
2 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
根据要求,这里有一个使用 outer
并显示比较 hp
和 disp
值的稍微更简洁(如果不那么混乱)的方法。它还利用 reshape2::melt
:
library(dplyr)
f <- function(x) {
y <- reshape2::melt(outer(x$disp, x$disp, `>`) & outer(x$hp, x$hp, `>`))
y <- y[y[[1]] != y[[2]],]
tibble(Car1 = rownames(x)[y[[1]]], Car2 = rownames(x)[y[[2]]],
disp1 = x$disp[y[[1]]], disp2 = x$disp[y[[2]]],
hp1 = x$hp[y[[1]]], hp2 = x$hp[y[[2]]], result = y[[3]])
}
result_list <- mtcars %>% split(paste(.$gear, .$am)) %>% lapply(f)
结果列表中每个档位/上午组合都有一个数据框。为了简洁起见,我只在这里展示了第二个:
result_list[2]
$`4 0`
# A tibble: 12 x 7
Car1 Car2 disp1 disp2 hp1 hp2 result
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <lgl>
1 Merc 230 Merc 240D 141. 147. 95 62 FALSE
2 Merc 280 Merc 240D 168. 147. 123 62 TRUE
3 Merc 280C Merc 240D 168. 147. 123 62 TRUE
4 Merc 240D Merc 230 147. 141. 62 95 FALSE
5 Merc 280 Merc 230 168. 141. 123 95 TRUE
6 Merc 280C Merc 230 168. 141. 123 95 TRUE
7 Merc 240D Merc 280 147. 168. 62 123 FALSE
8 Merc 230 Merc 280 141. 168. 95 123 FALSE
9 Merc 280C Merc 280 168. 168. 123 123 FALSE
10 Merc 240D Merc 280C 147. 168. 62 123 FALSE
11 Merc 230 Merc 280C 141. 168. 95 123 FALSE
12 Merc 280 Merc 280C 168. 168. 123 123 FALSE
我们有 mtcars
数据集,想要计算一组不同汽车之间的函数,将几列作为输入。
更具体地说:
- 按变速箱
am
和齿轮gear
分组
- 比较同一组中的所有汽车(car1 到 car2、car1 到 car3、car2 到 car3...)
- 第一辆车的排量是否比第二辆车大?
disp1>disp2
- 并且第一辆车的马力是否比第二辆车大?
hp1>hp2
结果应如下所示:
# Car1 Car2 result
# Mazda RX4 Mazda RX4 Wag false
# Mazda RX4 Datsun 710 false
# Mazda RX4 Wag Datsun 710 true
在
disp1
、disp2
等列
这有点乱,但您可以执行以下操作:
library(dplyr)
library(tidyr)
dat <- mtcars %>%
tibble::rownames_to_column(var = "Car1") %>%
mutate(Car2 = Car1) %>%
group_by(am, gear) %>%
expand(Car1, Car2) %>%
left_join(tibble::rownames_to_column(mtcars, var = "Car1"), by = "Car1") %>%
left_join(tibble::rownames_to_column(mtcars, var = "Car2"), by = "Car2") %>%
ungroup() %>%
mutate(result = disp.x > disp.y & hp.x > hp.y) %>%
select(Car1, Car2, result)
然后我们得到了预期的结果:
dat
# A tibble: 330 x 3
Car1 Car2 result
<chr> <chr> <lgl>
1 AMC Javelin AMC Javelin FALSE
2 AMC Javelin Cadillac Fleetwood FALSE
3 AMC Javelin Camaro Z28 FALSE
4 AMC Javelin Chrysler Imperial FALSE
5 AMC Javelin Dodge Challenger FALSE
6 AMC Javelin Duster 360 FALSE
7 AMC Javelin Hornet 4 Drive TRUE
8 AMC Javelin Hornet Sportabout FALSE
9 AMC Javelin Lincoln Continental FALSE
10 AMC Javelin Merc 450SE FALSE
# … with 320 more rows
dat %>% filter(Car1 == "Mazda RX4")
# A tibble: 8 x 3
Car1 Car2 result
<chr> <chr> <lgl>
1 Mazda RX4 Datsun 710 TRUE
2 Mazda RX4 Fiat 128 TRUE
3 Mazda RX4 Fiat X1-9 TRUE
4 Mazda RX4 Honda Civic TRUE
5 Mazda RX4 Mazda RX4 FALSE
6 Mazda RX4 Mazda RX4 Wag FALSE
7 Mazda RX4 Toyota Corolla TRUE
8 Mazda RX4 Volvo 142E TRUE
(虽然马自达 RX4 与 Datsun 710 的比较与您陈述的预期结果不同,但实际上是正确的:)
mtcars %>%
tibble::rownames_to_column(var = "Car1") %>%
filter(Car1 %in% c("Mazda RX4", "Datsun 710"))
Car1 mpg cyl disp hp drat wt qsec vs am gear carb
1 Mazda RX4 21.0 6 160 110 3.90 2.62 16.46 0 1 4 4
2 Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1
根据要求,这里有一个使用 outer
并显示比较 hp
和 disp
值的稍微更简洁(如果不那么混乱)的方法。它还利用 reshape2::melt
:
library(dplyr)
f <- function(x) {
y <- reshape2::melt(outer(x$disp, x$disp, `>`) & outer(x$hp, x$hp, `>`))
y <- y[y[[1]] != y[[2]],]
tibble(Car1 = rownames(x)[y[[1]]], Car2 = rownames(x)[y[[2]]],
disp1 = x$disp[y[[1]]], disp2 = x$disp[y[[2]]],
hp1 = x$hp[y[[1]]], hp2 = x$hp[y[[2]]], result = y[[3]])
}
result_list <- mtcars %>% split(paste(.$gear, .$am)) %>% lapply(f)
结果列表中每个档位/上午组合都有一个数据框。为了简洁起见,我只在这里展示了第二个:
result_list[2]
$`4 0`
# A tibble: 12 x 7
Car1 Car2 disp1 disp2 hp1 hp2 result
<chr> <chr> <dbl> <dbl> <dbl> <dbl> <lgl>
1 Merc 230 Merc 240D 141. 147. 95 62 FALSE
2 Merc 280 Merc 240D 168. 147. 123 62 TRUE
3 Merc 280C Merc 240D 168. 147. 123 62 TRUE
4 Merc 240D Merc 230 147. 141. 62 95 FALSE
5 Merc 280 Merc 230 168. 141. 123 95 TRUE
6 Merc 280C Merc 230 168. 141. 123 95 TRUE
7 Merc 240D Merc 280 147. 168. 62 123 FALSE
8 Merc 230 Merc 280 141. 168. 95 123 FALSE
9 Merc 280C Merc 280 168. 168. 123 123 FALSE
10 Merc 240D Merc 280C 147. 168. 62 123 FALSE
11 Merc 230 Merc 280C 141. 168. 95 123 FALSE
12 Merc 280 Merc 280C 168. 168. 123 123 FALSE