I have a function like this
adstock <- function(x, rate) {
adstocked_variable <- x
for (i in 1:(length(x)-1) ) {
adstocked_variable[i+1] <- x[i + 1] + (rate * adstocked_variable[i])
}
adstocked_variable
}
And a vector of rates like so:
rates <- seq(0.00, 1, 0.25)
How can I map the adstock function to every column in mtcars, once for every number in the rates vector?
I want the output to look something like this:
$mpg
mpg_0.00 mpg_0.25 mpg_0.5
1 21.0 21.00000 21.00000
2 21.0 26.25000 31.50000
3 22.8 29.36250 38.55000
4 21.4 28.74062 40.67500
5 18.7 25.88516 39.03750
6 18.1 24.57129 37.61875
7 14.3 20.44282 33.10938
8 24.4 29.51071 40.95469
$cyl
cyl_0.00 cyl_0.25 cyl_0.5
1 6 6.000000 6.000000
2 6 7.500000 9.000000
3 4 5.875000 8.500000
4 6 7.468750 10.250000
5 8 9.867188 13.125000
6 6 8.466797 12.562500
7 8 10.116699 14.281250
8 4 6.529175 11.140625
I have tried variations of the following with no sucess
library(tidyverse)
mtcars %>%
map(~adstock(., rates))
Here is one idea.
library(purrr)
imap(mtcars, ~map_dfc(rates, function(x){
dat <- data.frame(adstock(.x, x))
}) %>%
set_names(paste(.y, rates, sep = "_"))
)
# $mpg
# mpg_0 mpg_0.25 mpg_0.5 mpg_0.75 mpg_1
# 1 21.0 21.00000 21.00000 21.00000 21.0
# 2 21.0 26.25000 31.50000 36.75000 42.0
# 3 22.8 29.36250 38.55000 50.36250 64.8
# 4 21.4 28.74062 40.67500 59.17187 86.2
# 5 18.7 25.88516 39.03750 63.07891 104.9
# 6 18.1 24.57129 37.61875 65.40918 123.0
# 7 14.3 20.44282 33.10938 63.35688 137.3
# 8 24.4 29.51071 40.95469 71.91766 161.7
# 9 22.8 30.17768 43.27734 76.73825 184.5
# 10 19.2 26.74442 40.83867 76.75369 203.7
# 11 17.8 24.48610 38.21934 75.36526 221.5
# 12 16.4 22.52153 35.50967 72.92395 237.9
# 13 17.3 22.93038 35.05483 71.99296 255.2
# 14 15.2 20.93260 32.72742 69.19472 270.4
# 15 10.4 15.63315 26.76371 62.29604 280.8
# 16 10.4 14.30829 23.78185 57.12203 291.2
# 17 14.7 18.27707 26.59093 57.54152 305.9
# 18 32.4 36.96927 45.69546 75.55614 338.3
# 19 30.4 39.64232 53.24773 87.06711 368.7
# 20 33.9 43.81058 60.52387 99.20033 402.6
# 21 21.5 32.45264 51.76193 95.90025 424.1
# 22 15.5 23.61316 41.38097 87.42519 439.6
# 23 15.2 21.10329 35.89048 80.76889 454.8
# 24 13.3 18.57582 31.24524 73.87667 468.1
# 25 19.2 23.84396 34.82262 74.60750 487.3
# 26 27.3 33.26099 44.71131 83.25563 514.6
# 27 26.0 34.31525 48.35566 88.44172 540.6
# 28 30.4 38.97881 54.57783 96.73129 571.0
# 29 15.8 25.54470 43.08891 88.34847 586.8
# 30 19.7 26.08618 41.24446 85.96135 606.5
# 31 15.0 21.52154 35.62223 79.47101 621.5
# 32 21.4 26.78039 39.21111 81.00326 642.9
# ...
Related
I have one folder for each subject in my study containing 2-5 csv data which i would like to bind together. For each subject/folder the names of the data are the same.
I want to bind the data for each subject and would like to create a loop. As I have 230 different subjects doing that manually with rbind would be overhelming. The foldername is the subjectID
Any Ideas?
FolderStructure:
subject1/day1.csv
subject1/day2.csv
subject1/day3.csv
subject2/day1.csv
subject2/day2.csv
subject3/day1.csv
subject3/day2.csv
subject3/day3.csv
...
I'll demo using dplyr::bind_rows, though it'll work just as well with data.table::rbindlist. The base-R variant do.call(rbind, ...) does not work as directly since it doesn't have the .id=/idcol= easy option (some elbow-grease can work around this).
list_of_files ## make this however you want
# [1] "sub1/day1.csv" "sub1/day2.csv" "sub2/day1.csv" "sub2/day2.csv"
alldat <- lapply(setNames(nm=list_of_files), read.csv)
### fake data for demonstration
# alldat <- setNames(replicate(4, mtcars[sample(32,3),], simplify=FALSE), list_of_files)
lapply(split(alldat, sub("/.*", "", names(alldat))), dplyr::bind_rows, .id = "subj")
# $sub1
# subj mpg cyl disp hp drat wt qsec vs am gear carb
# Merc 230 sub1/day1.csv 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2
# Lincoln Continental sub1/day1.csv 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
# Merc 450SE sub1/day1.csv 16.4 8 275.8 180 3.07 4.070 17.40 0 0 3 3
# Porsche 914-2 sub1/day2.csv 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
# Fiat 128 sub1/day2.csv 32.4 4 78.7 66 4.08 2.200 19.47 1 1 4 1
# Toyota Corona sub1/day2.csv 21.5 4 120.1 97 3.70 2.465 20.01 1 0 3 1
# $sub2
# subj mpg cyl disp hp drat wt qsec vs am gear carb
# Mazda RX4 sub2/day1.csv 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
# Fiat X1-9 sub2/day1.csv 27.3 4 79.0 66 4.08 1.935 18.90 1 1 4 1
# Lincoln Continental sub2/day1.csv 10.4 8 460.0 215 3.00 5.424 17.82 0 0 3 4
# Merc 240D sub2/day2.csv 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2
# Merc 450SLC sub2/day2.csv 15.2 8 275.8 180 3.07 3.780 18.00 0 0 3 3
# Hornet 4 Drive sub2/day2.csv 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
You now have a list, one element per subject.
You can solve this problem easily by using read_csv from readr package and by obtaining paths of files in each of subjectID folders.
Let's suppose I have three folders subject1, subject2, subject3 which has csv files with same columns but with different rows.
library(readr)
subjects <- 3
paths <- sort(list.files(recursive = TRUE))
paths
[1] "subject1/cars1.csv" "subject1/cars2.csv" "subject1/cars3.csv"
[4] "subject2/cars1.csv" "subject2/cars2.csv" "subject3/cars1.csv"
[7] "subject3/cars2.csv" "subject3/cars3.csv"
So we can see subject1 folder has 3 csv files, subject2 has 2 csv files and sunject3 folder has 3 csv files. All we need to group these paths to csv files for each subjects folder and give each group of paths to read_csv
for (i in seq_len(subjects)) {
subj <- paste0("subject", i)
subject_paths <- paths[grepl(subj, paths)]
file_name <- paste0("subject_", i, "_binded")
assign(file_name, readr::read_csv(subject_paths, id = "paths"))
}
This will create three binded dataframe each for each subject folder.
> subject_1_binded
# A tibble: 15 × 4
paths mpg cyl disp
<chr> <dbl> <dbl> <dbl>
1 subject1/cars1.csv 27.3 4 79
2 subject1/cars1.csv 21 6 160
3 subject1/cars1.csv 13.3 8 350
4 subject1/cars1.csv 19.2 8 400
5 subject1/cars1.csv 10.4 8 460
6 subject1/cars2.csv 14.7 8 440
7 subject1/cars2.csv 18.7 8 360
8 subject1/cars2.csv 30.4 4 95.1
9 subject1/cars2.csv 15.5 8 318
10 subject1/cars2.csv 16.4 8 276.
11 subject1/cars3.csv 21.5 4 120.
12 subject1/cars3.csv 15.5 8 318
13 subject1/cars3.csv 19.7 6 145
14 subject1/cars3.csv 14.3 8 360
15 subject1/cars3.csv 21.4 4 121
> subject_2_binded
# A tibble: 15 × 4
paths mpg cyl disp
<chr> <dbl> <dbl> <dbl>
1 subject2/cars1.csv 27.3 4 79
2 subject2/cars1.csv 21 6 160
3 subject2/cars1.csv 13.3 8 350
4 subject2/cars1.csv 19.2 8 400
5 subject2/cars1.csv 10.4 8 460
6 subject2/cars2.csv 14.7 8 440
7 subject2/cars2.csv 18.7 8 360
8 subject2/cars2.csv 30.4 4 95.1
9 subject2/cars2.csv 15.5 8 318
10 subject2/cars2.csv 16.4 8 276.
11 subject2/cars3.csv 21.5 4 120.
12 subject2/cars3.csv 15.5 8 318
13 subject2/cars3.csv 19.7 6 145
14 subject2/cars3.csv 14.3 8 360
15 subject2/cars3.csv 21.4 4 121
> subject_3_binded
# A tibble: 15 × 4
paths mpg cyl disp
<chr> <dbl> <dbl> <dbl>
1 subject3/cars1.csv 27.3 4 79
2 subject3/cars1.csv 21 6 160
3 subject3/cars1.csv 13.3 8 350
4 subject3/cars1.csv 19.2 8 400
5 subject3/cars1.csv 10.4 8 460
6 subject3/cars2.csv 14.7 8 440
7 subject3/cars2.csv 18.7 8 360
8 subject3/cars2.csv 30.4 4 95.1
9 subject3/cars2.csv 15.5 8 318
10 subject3/cars2.csv 16.4 8 276.
11 subject3/cars3.csv 21.5 4 120.
12 subject3/cars3.csv 15.5 8 318
13 subject3/cars3.csv 19.7 6 145
14 subject3/cars3.csv 14.3 8 360
15 subject3/cars3.csv 21.4 4 121
So In your case for your 230 subjects you will have 230 binded data.
Note the use of assign() in the last line of for-loop, for your case it would create 230 data.frame (more appropriately, tbl_df) object in your global environment.
I want to be able to pass a function an undefined number of arguments via ... but also to be able to pass it a vector. Here is a silly example:
library(tidyverse)
df <- data.frame(gear = as.character(unique(mtcars$gear)),
id = 1:3)
myfun <- function(...) {
ids_lst <- lst(...)
df2 <- bind_rows(map(ids_lst, function(x)
mtcars %>%
filter(gear == x) %>%
select(mpg)), .id = "gear") %>%
left_join(df)
df2
}
#these all work:
myfun(3)
myfun(3, 4)
myfun(3, 4, 5)
Passing it a vector doesn't work though:
myvector <- unique(mtcars$gear)
myfun(myvector)
The problem is because of the way the function collects the arguments and how it returns them:
myfun_lst <- function(...) {
ids_lst <- lst(...)
ids_lst
}
myfun_lst(3, 4, 5)
# $`3`
# [1] 3
# $`4`
# [1] 4
# $`5`
# [1] 5
myfun_lst(myvector)
# $myvector
# [1] 4 3 5
I thought a fix would be to test if the input is a vector, something like:
myfun_final <- function(...) {
if(is.vector(...) & !is.list(...)) {
ids_lst <- as.list(...)
names(ids_lst) <- (...)
} else {
ids_lst <- lst(...)
}
df2 <- bind_rows(map(ids_lst, function(x)
mtcars %>%
filter(gear == x) %>%
select(mpg)), .id = "gear") %>%
left_join(df)
df2
}
Now, passing the function a vector works but collecting the arguments doesn't:
myfun_final(3, 4, 5)
myfun_final(myvector)
What is a good way to solve this?
Thanks
Of course you can change your function so that it will work with both, regular arguments myfun(3, 4, 5) and a vector myfun(myvector), as shown in the answer above.
Another option is that you make use of argument splicing by unquoting with the bang bang bang operator !!!. This operator is only supported in certain {rlang} and {tidyverse} functions. In your example you evaluate the dots ... inside purrr::map which supports argument splicing. Therefore there might not be the need to rewrite your function:
library(tidyverse)
# your original function:
myfun <- function(...) {
ids_lst <- lst(...)
df2 <- bind_rows(map(ids_lst, function(x)
mtcars %>%
filter(gear == x) %>%
select(mpg)), .id = "gear") %>%
left_join(df)
df2
}
myvector <- unique(mtcars$gear)
myfun(!!! myvector) # works
#> Joining, by = "gear"
#> gear mpg id
#> 1 4 21.0 1
#> 2 4 21.0 1
#> 3 4 22.8 1
#> 4 4 24.4 1
#> 5 4 22.8 1
#> 6 4 19.2 1
#> 7 4 17.8 1
#> 8 4 32.4 1
#> 9 4 30.4 1
#> 10 4 33.9 1
#> ...
myfun(3, 4, 5) # works
#> Joining, by = "gear"
#> gear mpg id
#> 1 3 21.4 2
#> 2 3 18.7 2
#> 3 3 18.1 2
#> 4 3 14.3 2
#> 5 3 16.4 2
#> 6 3 17.3 2
#> 7 3 15.2 2
#> 8 3 10.4 2
#> 9 3 10.4 2
#> 10 3 14.7 2
#> ...
Created on 2021-12-30 by the reprex package (v0.3.0)
You can read more about unquoting with the bang bang bang operator here.
Finally, you should think about the users of your function. If you are the only user then choose whatever suits you. In case there are other users you should think about how they expect the function to work. Probably users don't expect a function to work with several arguments and at the same time, alternatively, by providing those arguments in a vector. In the tidyverse argument splicing with !!! is a well established concept. In base R we would usually use do.call("myfun", as.list(myvector)) to achieve something similar.
To add another option:
The purrr package has a family of lift functions which can be used to alter the kind of arguments a function takes. The most prominent is lift_dl which transforms a function that takes dots as argument to a function that takes a list or vector as argument. This could also be used to solve the problem without the need to rewrite the function:
lift_dl(myfun)(myvector)
#> Joining, by = "gear"
#> gear mpg id
#> 1 4 21.0 1
#> 2 4 21.0 1
#> 3 4 22.8 1
#> 4 4 24.4 1
#> 5 4 22.8 1
#> 6 4 19.2 1
#> 7 4 17.8 1
#> 8 4 32.4 1
#> 9 4 30.4 1
#> 10 4 33.9 1
#> ...
Created on 2022-01-01 by the reprex package (v0.3.0)
How about testing if ... is of length 1 and if the only argument passed through is a vector? If not so, then consider ... a list of scalers and capture them with lst(...).
myfun_final <- function(...) {
if (...length() == 1L && is.vector(..1))
ids_lst <- `names<-`(..1, ..1)
else
ids_lst <- lst(...)
df2 <- bind_rows(map(ids_lst, function(x)
mtcars %>%
filter(gear == x) %>%
select(mpg)), .id = "gear") %>%
left_join(df)
df2
}
Test
> myfun_final(3)
Joining, by = "gear"
gear mpg id
1 3 21.4 2
2 3 18.7 2
3 3 18.1 2
4 3 14.3 2
5 3 16.4 2
6 3 17.3 2
7 3 15.2 2
8 3 10.4 2
9 3 10.4 2
10 3 14.7 2
11 3 21.5 2
12 3 15.5 2
13 3 15.2 2
14 3 13.3 2
15 3 19.2 2
> myfun_final(3,4,5)
Joining, by = "gear"
gear mpg id
1 3 21.4 2
2 3 18.7 2
3 3 18.1 2
4 3 14.3 2
5 3 16.4 2
6 3 17.3 2
7 3 15.2 2
8 3 10.4 2
9 3 10.4 2
10 3 14.7 2
11 3 21.5 2
12 3 15.5 2
13 3 15.2 2
14 3 13.3 2
15 3 19.2 2
16 4 21.0 1
17 4 21.0 1
18 4 22.8 1
19 4 24.4 1
20 4 22.8 1
21 4 19.2 1
22 4 17.8 1
23 4 32.4 1
24 4 30.4 1
25 4 33.9 1
26 4 27.3 1
27 4 21.4 1
28 5 26.0 3
29 5 30.4 3
30 5 15.8 3
31 5 19.7 3
32 5 15.0 3
> myfun_final(c(3,4,5))
Joining, by = "gear"
gear mpg id
1 3 21.4 2
2 3 18.7 2
3 3 18.1 2
4 3 14.3 2
5 3 16.4 2
6 3 17.3 2
7 3 15.2 2
8 3 10.4 2
9 3 10.4 2
10 3 14.7 2
11 3 21.5 2
12 3 15.5 2
13 3 15.2 2
14 3 13.3 2
15 3 19.2 2
16 4 21.0 1
17 4 21.0 1
18 4 22.8 1
19 4 24.4 1
20 4 22.8 1
21 4 19.2 1
22 4 17.8 1
23 4 32.4 1
24 4 30.4 1
25 4 33.9 1
26 4 27.3 1
27 4 21.4 1
28 5 26.0 3
29 5 30.4 3
30 5 15.8 3
31 5 19.7 3
32 5 15.0 3
I hope I can explain what I'm trying to do sufficiently. I'm working in R and for a dataset I'm trying to keep only observations where for one variable, another variable satisfies two conditions.
Specifically, I want to keep only rows where for a particular "cyl", there is at least one mpg value >20, and at least one <20. Here is some example data from mtcars similar to what I'm working with.
mpg cyl
1 21.0 6
2 21.0 6
3 22.8 4
4 21.4 6
5 18.7 8
6 18.1 6
7 14.3 8
8 24.4 4
9 22.8 4
10 19.2 6
11 17.8 6
12 16.4 8
13 17.3 8
14 15.2 8
15 10.4 8
16 10.4 8
17 14.7 8
18 32.4 4
19 30.4 4
20 33.9 4
Ideally, my output for the above example would be what's below.
mpg cyl
1 21.0 6
2 21.0 6
4 21.4 6
6 18.1 6
10 19.2 6
11 17.8 6
Thanks in advance!
Assuming your dataframe input is DF, try this:
library(dplyr)
DF %>%
group_by(cyl) %>%
filter(sum(mpg > 20) > 1 & sum(mpg < 20) > 1)
# A tibble: 7 x 2
# Groups: cyl [1]
# mpg cyl
# <dbl> <dbl>
# 1 21 6
# 2 21 6
# 3 21.4 6
# 4 18.1 6
# 5 19.2 6
# 6 17.8 6
# 7 19.7 6
data
DF <- mtcars[,1:2]
I haven't come across this problem before. I'd like to sort multiple columns as ascending or descending within a group depending on a condition
library(dplyr)
data <- mtcars %>% select(mpg, cyl, disp)
If cyl <= 4, I'd like to sort mpg, disp (in that priority) in ascending order. If cyl > 4, I'd like to sort mpg, disp in descending order.
expected <- rbind(
filter(data, cyl <= 4) %>% arrange(mpg, disp),
filter(data, cyl > 4) %>% arrange(cyl, desc(mpg), desc(disp))
)
Multiply each variable to be possibly reversed by sign(4.1 - cyl) :
mtcars %>% arrange(cyl, sign(4.1 - cyl) * mpg, sign(4.1 - cyl) * disp)
If mpg, say, were not numeric one could still do it by replacing mpg with xtfrm(mpg) which would map it to a numeric. See ?xtfrm .
We can convert the values to negative to create new columns and then sort those columns.
library(dplyr)
data2 <- data %>%
mutate_at(vars(mpg, cyl), funs(ifelse(cyl <= 4, ., -.))) %>%
arrange(cyl, mpg2, disp2) %>%
select(-ends_with("2"))
data2
# mpg cyl disp
# 1 21.4 4 121.0
# 2 21.5 4 120.1
# 3 22.8 4 108.0
# 4 22.8 4 140.8
# 5 24.4 4 146.7
# 6 26.0 4 120.3
# 7 27.3 4 79.0
# 8 30.4 4 75.7
# 9 30.4 4 95.1
# 10 32.4 4 78.7
# 11 33.9 4 71.1
# 12 21.4 6 258.0
# 13 21.0 6 160.0
# 14 21.0 6 160.0
# 15 19.7 6 145.0
# 16 19.2 6 167.6
# 17 18.1 6 225.0
# 18 17.8 6 167.6
# 19 19.2 8 400.0
# 20 18.7 8 360.0
# 21 17.3 8 275.8
# 22 16.4 8 275.8
# 23 15.8 8 351.0
# 24 15.5 8 318.0
# 25 15.2 8 304.0
# 26 15.2 8 275.8
# 27 15.0 8 301.0
# 28 14.7 8 440.0
# 29 14.3 8 360.0
# 30 13.3 8 350.0
# 31 10.4 8 472.0
# 32 10.4 8 460.0
So I've got a dataset that looks something like this:
a b c
23 34 Falcons
14 9 Hawks
2 18 Eagles
3 21 Eagles
22 8 Falcons
11 4 Hawks
And I know I can do a random subset of rows with a nested conditional, but what I want to do is create a random subset that takes at least one of each available value in column 'c'.
So possible correct subsets would be
23 34 Falcons
14 9 Hawks
3 21 Eagles
or
11 4 Hawks
2 18 Eagles
22 8 Falcons
[in no particular order], but something like:
14 9 Hawks
2 18 Eagles
3 21 Eagles
would NOT work, because 'Falcons' is not represented. Is there an easy way to do this in R?
Use group_by and sample_n functions in the dplyr package.
text1 <- "a b c
23 34 Falcons
14 9 Hawks
2 18 Eagles
3 21 Eagles
22 8 Falcons
11 4 Hawks"
dat <- read.table(text=text1, head=T, as.is=T)
library(dplyr)
dat %>% group_by(c) %>% sample_n(1)
# Source: local data frame [3 x 3]
# Groups: c [3]
# a b c
# (int) (int) (chr)
# 1 3 21 Eagles
# 2 22 8 Falcons
# 3 11 4 Hawks
UPDATE: You can write a function to do the sampling.
sample_df <- function(df) {
df.r <- sample(1:nrow(df), 1)
return(sample_n(df, df.r))
}
dat %>% group_by(c) %>% do(sample_df(.))
You can specify the n for each group here (use 1s if you only want a data frame with nrows == number of groups
dd <- read.table(header = TRUE, text = 'a b c
23 34 Falcons
14 9 Hawks
2 18 Eagles
3 21 Eagles
22 8 Falcons
11 4 Hawks', stringsAsFactors = FALSE)
(n <- setNames(c(1,2,1), unique(dd$c)))
# Falcons Hawks Eagles
# 1 2 1
set.seed(1)
dd[as.logical(ave(dd$c, dd$c, FUN = function(x)
sample(rep(c(FALSE, TRUE), c(length(x) - n[x[1]], n[x[1]]))))), ]
# a b c
# 1 23 34 Falcons
# 2 14 9 Hawks
# 4 3 21 Eagles
# 6 11 4 Hawks
Putting this into a function to automate some other things for you
sample_each <- function(data, var, n = 1L) {
lvl <- table(data[, var])
n1 <- setNames(rep_len(n, length(lvl)), names(lvl))
n0 <- lvl - n1
idx <- ave(as.character(data[, var]), data[, var], FUN = function(x)
sample(rep(0:1, c(n0[x[1]], n1[x[1]]))))
data[!!(as.numeric(idx)), ]
}
sample_each(dd, 'c', n = c(1,2,1))
# a b c
# 1 23 34 Falcons
# 3 2 18 Eagles
# 5 22 8 Falcons
# 6 11 4 Hawks
sample_each(mtcars, 'gear', 1)
# mpg cyl disp hp drat wt qsec vs am gear carb
# Valiant 18.1 6 225.0 105 2.76 3.46 20.22 1 0 3 1
# Merc 280 19.2 6 167.6 123 3.92 3.44 18.30 1 0 4 4
# Maserati Bora 15.0 8 301.0 335 3.54 3.57 14.60 0 1 5 8
sample_each(mtcars, 'gear', c(2,2,5))
# mpg cyl disp hp drat wt qsec vs am gear carb
# Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
# Porsche 914-2 26.0 4 120.3 91 4.43 2.140 16.70 0 1 5 2
# Lotus Europa 30.4 4 95.1 113 3.77 1.513 16.90 1 1 5 2
# Ford Pantera L 15.8 8 351.0 264 4.22 3.170 14.50 0 1 5 4
# Ferrari Dino 19.7 6 145.0 175 3.62 2.770 15.50 0 1 5 6
# Maserati Bora 15.0 8 301.0 335 3.54 3.570 14.60 0 1 5 8
# Mazda RX4 Wag1 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
# Hornet Sportabout1 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
# Merc 2801 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4