dplyrs 单表动词

dplyr 在 R引入了数据操作的语法。它提供了一致的界面来处理数据,无论数据存储在何处: data.framedata.tabledatabasedplyr 的关键部分是使用 Rcpp编写的,这使得处理内存数据的速度非常快。

dplyr 的理念是拥有能够做到一件好事的小功能。五个简单函数(filterarrangeselectmutatesummarise)可用于揭示描述数据的新方法。当与 group_by 结合使用时,这些函数可用于计算分组汇总统计信息。

语法共性

所有这些函数都有类似的语法:

  • 所有这些函数的第一个参数始终是数据框
  • 可以使用裸变量名称直接引用列(即,不使用 $
  • 这些功能不会修改原始数据本身,即它们没有副作用。因此,结果应始终保存到对象中。

我们将使用内置的 mtcars 数据集来探索 dplyr 的单表动词。mtcars 的类型转换为 tbl_df(因为它使打印清洁器)之前,我们添加的数据集的 rownames 如使用 rownames_to_column 函数从一列 tibble 包。

library(dplyr) # This documentation was written using version 0.5.0

mtcars_tbl <- as_data_frame(tibble::rownames_to_column(mtcars, "cars"))

# examine the structure of data
head(mtcars_tbl)

# A tibble: 6 x 12
#               cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#              <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1         Mazda RX4  21.0     6   160   110  3.90 2.620 16.46     0     1     4     4
#2     Mazda RX4 Wag  21.0     6   160   110  3.90 2.875 17.02     0     1     4     4
#3        Datsun 710  22.8     4   108    93  3.85 2.320 18.61     1     1     4     1
#4    Hornet 4 Drive  21.4     6   258   110  3.08 3.215 19.44     1     0     3     1
#5 Hornet Sportabout  18.7     8   360   175  3.15 3.440 17.02     0     0     3     2
#6           Valiant  18.1     6   225   105  2.76 3.460 20.22     1     0     3     1

过滤

filter 帮助符合特定条件的子集行。第一个参数是 data.frame 的名称,第二个(和后续)参数是过滤数据的标准(这些标准应评估为 TRUEFALSE

子集所有有 4 个汽缸的汽车 - cyl

filter(mtcars_tbl, cyl == 4) 

# A tibble: 11 x 12
#             cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#            <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1      Datsun 710  22.8     4 108.0    93  3.85 2.320 18.61     1     1     4     1
#2       Merc 240D  24.4     4 146.7    62  3.69 3.190 20.00     1     0     4     2
#3        Merc 230  22.8     4 140.8    95  3.92 3.150 22.90     1     0     4     2
#4        Fiat 128  32.4     4  78.7    66  4.08 2.200 19.47     1     1     4     1
#5     Honda Civic  30.4     4  75.7    52  4.93 1.615 18.52     1     1     4     2
# ... with 6 more rows

我们可以传递用逗号分隔的多个条件。对具有 4 或 6 个气缸的车辆进行分组 - cyl 并且有 5 个档位 - gear

filter(mtcars_tbl, cyl == 4 | cyl == 6, gear == 5)

# A tibble: 3 x 12
#           cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#          <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 Porsche 914-2  26.0     4 120.3    91  4.43 2.140  16.7     0     1     5     2
#2  Lotus Europa  30.4     4  95.1   113  3.77 1.513  16.9     1     1     5     2
#3  Ferrari Dino  19.7     6 145.0   175  3.62 2.770  15.5     0     1     5     6

filter 根据条件选择行,按位置选择行,使用 sliceslice 只有 2 个参数:第一个是 data.frame,第二个是整数行值。

要选择第 6 行到第 9 行:

slice(mtcars_tbl, 6:9)

# A tibble: 4 x 12
#        cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#       <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1    Valiant  18.1     6 225.0   105  2.76  3.46 20.22     1     0     3     1
#2 Duster 360  14.3     8 360.0   245  3.21  3.57 15.84     0     0     3     4
#3  Merc 240D  24.4     4 146.7    62  3.69  3.19 20.00     1     0     4     2
#4   Merc 230  22.8     4 140.8    95  3.92  3.15 22.90     1     0     4     2

要么:

slice(mtcars_tbl, -c(1:5, 10:n())) 

这导致与 slice(mtcars_tbl, 6:9) 相同的输出

n() 表示当前组中的观察数

安排

arrange 用于按指定的变量对数据进行排序。就像之前的动词(以及 dplyr 中的所有其他函数)一样,第一个参数是 data.frame,后续参数用于对数据进行排序。如果传递了多个变量,则数据首先按第一个变量排序,然后按第二个变量排序,依此类推。

马力订购数据 - hp

arrange(mtcars_tbl, hp) 

# A tibble: 32 x 12
#             cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#            <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1     Honda Civic  30.4     4  75.7    52  4.93 1.615 18.52     1     1     4     2
#2       Merc 240D  24.4     4 146.7    62  3.69 3.190 20.00     1     0     4     2
#3  Toyota Corolla  33.9     4  71.1    65  4.22 1.835 19.90     1     1     4     1
#4        Fiat 128  32.4     4  78.7    66  4.08 2.200 19.47     1     1     4     1
#5       Fiat X1-9  27.3     4  79.0    66  4.08 1.935 18.90     1     1     4     1
#6   Porsche 914-2  26.0     4 120.3    91  4.43 2.140 16.70     0     1     5     2
# ... with 26 more rows

每加仑英里数为单位来计算数据 - mpg 按降序排列,然后是气缸数 - cyl

arrange(mtcars_tbl, desc(mpg), cyl)

# A tibble: 32 x 12
#             cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#            <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1  Toyota Corolla  33.9     4  71.1    65  4.22 1.835 19.90     1     1     4     1
#2        Fiat 128  32.4     4  78.7    66  4.08 2.200 19.47     1     1     4     1
#3     Honda Civic  30.4     4  75.7    52  4.93 1.615 18.52     1     1     4     2
#4    Lotus Europa  30.4     4  95.1   113  3.77 1.513 16.90     1     1     5     2
#5       Fiat X1-9  27.3     4  79.0    66  4.08 1.935 18.90     1     1     4     1
#6   Porsche 914-2  26.0     4 120.3    91  4.43 2.140 16.70     0     1     5     2
# ... with 26 more rows

选择

select 用于仅选择变量的子集。要从 mtcars_tbl 中仅选择 mpgdispwtqsecvs

select(mtcars_tbl, mpg, disp, wt, qsec, vs)

# A tibble: 32 x 5
#     mpg  disp    wt  qsec    vs
#   <dbl> <dbl> <dbl> <dbl> <dbl>
#1   21.0 160.0 2.620 16.46     0
#2   21.0 160.0 2.875 17.02     0
#3   22.8 108.0 2.320 18.61     1
#4   21.4 258.0 3.215 19.44     1
#5   18.7 360.0 3.440 17.02     0
#6   18.1 225.0 3.460 20.22     1
# ... with 26 more rows

:表示法可用于选择连续的列。从 carsdispvscarb 选择列:

select(mtcars_tbl, cars:disp, vs:carb)

# A tibble: 32 x 8
#                cars   mpg   cyl  disp    vs    am  gear  carb
#               <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1          Mazda RX4  21.0     6 160.0     0     1     4     4
#2      Mazda RX4 Wag  21.0     6 160.0     0     1     4     4
#3         Datsun 710  22.8     4 108.0     1     1     4     1
#4     Hornet 4 Drive  21.4     6 258.0     1     0     3     1
#5  Hornet Sportabout  18.7     8 360.0     0     0     3     2
#6            Valiant  18.1     6 225.0     1     0     3     1
# ... with 26 more rows

或者 select(mtcars_tbl, -(hp:qsec))

对于包含多个列的数据集,按名称选择多个列可能会非常繁琐。为了让生活更轻松,有许多辅助功能(如 starts_with()ends_with()contains()matches()num_range()one_of()everything())可以在 select 中使用。要了解有关如何使用它们的更多信息,请参阅 ?select_helpers?select

注意 :直接在 select() 中引用列时,我们使用裸列名称,但在引用辅助函数中的列时应使用引号。

要在选择时重命名列:

select(mtcars_tbl, cylinders = cyl, displacement = disp) 

# A tibble: 32 x 2
#   cylinders displacement
#       <dbl>        <dbl>
#1          6        160.0
#2          6        160.0
#3          4        108.0
#4          6        258.0
#5          8        360.0
#6          6        225.0
# ... with 26 more rows

正如所料,这会丢弃所有其他变量。

要重命名列而不删除其他变量,请使用 rename

rename(mtcars_tbl, cylinders = cyl, displacement = disp)

# A tibble: 32 x 12
#                cars   mpg cylinders displacement    hp  drat    wt  qsec    vs
#               <chr> <dbl>     <dbl>        <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1          Mazda RX4  21.0         6        160.0   110  3.90 2.620 16.46     0
#2      Mazda RX4 Wag  21.0         6        160.0   110  3.90 2.875 17.02     0
#3         Datsun 710  22.8         4        108.0    93  3.85 2.320 18.61     1
#4     Hornet 4 Drive  21.4         6        258.0   110  3.08 3.215 19.44     1
#5  Hornet Sportabout  18.7         8        360.0   175  3.15 3.440 17.02     0
#6            Valiant  18.1         6        225.0   105  2.76 3.460 20.22     1
# ... with 26 more rows, and 3 more variables: am <dbl>, gear <dbl>, carb <dbl>

变异

mutate 可用于向数据添加新列。与 dplyr 中的所有其他函数一样,mutate 不会将新创建的列添加到原始数据中。列在 data.frame 的末尾添加。

mutate(mtcars_tbl, weight_ton = wt/2, weight_pounds = weight_ton * 2000)

# A tibble: 32 x 14
#                cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb weight_ton weight_pounds
#               <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>      <dbl>         <dbl>
#1          Mazda RX4  21.0     6 160.0   110  3.90 2.620 16.46     0     1     4     4     1.3100          2620
#2      Mazda RX4 Wag  21.0     6 160.0   110  3.90 2.875 17.02     0     1     4     4     1.4375          2875
#3         Datsun 710  22.8     4 108.0    93  3.85 2.320 18.61     1     1     4     1     1.1600          2320
#4     Hornet 4 Drive  21.4     6 258.0   110  3.08 3.215 19.44     1     0     3     1     1.6075          3215
#5  Hornet Sportabout  18.7     8 360.0   175  3.15 3.440 17.02     0     0     3     2     1.7200          3440
#6            Valiant  18.1     6 225.0   105  2.76 3.460 20.22     1     0     3     1     1.7300          3460
# ... with 26 more rows

注意在创建 weight_pounds 时使用 weight_ton。与基础 R 不同,mutate 允许我们引用刚刚创建的列用于后续操作。

要仅保留新创建的列,请使用 transmute 而不是 mutate

transmute(mtcars_tbl, weight_ton = wt/2, weight_pounds = weight_ton * 2000)

# A tibble: 32 x 2
#   weight_ton weight_pounds
#        <dbl>         <dbl>
#1      1.3100          2620
#2      1.4375          2875
#3      1.1600          2320
#4      1.6075          3215
#5      1.7200          3440
#6      1.7300          3460
# ... with 26 more rows

总结

summarise 通过将多个值折叠为单个值来计算变量的汇总统计信息。它可以计算多个统计信息,我们可以在同一语句中命名这些汇总列。

要计算数据集中所有汽车的 mpgdisp平均值标准差

summarise(mtcars_tbl, mean_mpg = mean(mpg), sd_mpg = sd(mpg), 
          mean_disp = mean(disp), sd_disp = sd(disp))

# A tibble: 1 x 4
#  mean_mpg   sd_mpg mean_disp  sd_disp
#     <dbl>    <dbl>     <dbl>    <dbl>
#1 20.09062 6.026948  230.7219 123.9387

group_by

group_by 可用于对数据执行分组操作。当上面定义的谓词应用于此分组数据时,它们将自动分别应用于每个组。

为了找到 meansdmpgcyl

by_cyl <- group_by(mtcars_tbl, cyl)
summarise(by_cyl, mean_mpg = mean(mpg), sd_mpg = sd(mpg))

# A tibble: 3 x 3
#    cyl mean_mpg   sd_mpg
#  <dbl>    <dbl>    <dbl>
#1     4 26.66364 4.509828
#2     6 19.74286 1.453567
#3     8 15.10000 2.560048

把它全部放在一起

我们从 carshpgear 选择列,按 cyl 排序行,从最高到最低 mpg 排序,按 gear 分组数据,最后只有那些车的子集有 mpg> 20 和 hp> 75

selected <- select(mtcars_tbl, cars:hp, gear)
ordered <- arrange(selected, cyl, desc(mpg))
by_cyl <- group_by(ordered, gear)
filter(by_cyl, mpg > 20, hp > 75)

Source: local data frame [9 x 6]
Groups: gear [3]

#            cars   mpg   cyl  disp    hp  gear
#           <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#1   Lotus Europa  30.4     4  95.1   113     5
#2  Porsche 914-2  26.0     4 120.3    91     5
#3     Datsun 710  22.8     4 108.0    93     4
#4       Merc 230  22.8     4 140.8    95     4
#5  Toyota Corona  21.5     4 120.1    97     3
# ... with 4 more rows

也许我们对中间结果不感兴趣,我们可以通过包装函数调用来实现与上面相同的结果:

filter(
    group_by(
        arrange(
            select(
                mtcars_tbl, cars:hp
            ), cyl, desc(mpg)
        ), cyl   
    ),mpg > 20, hp > 75 
)

这可能有点难以阅读。因此,可以使用管道 %>%运算符链接 dplyr 操作。以上代码转换为:

mtcars_tbl %>% 
    select(cars:hp) %>% 
    arrange(cyl, desc(mpg)) %>%
    group_by(cyl) %>% 
    filter(mpg > 20, hp > 75) 

总结多列

dplyr 提供 summarise_all() 以将函数应用于所有(非分组)列。

要查找每列的不同值的数量,请执行以下操作:

mtcars_tbl %>% 
    summarise_all(n_distinct)

# A tibble: 1 x 12
#   cars   mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb
#  <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#1    32    25     3    27    22    22    29    30     2     2     3     6

要通过 cyl 查找每列的不同值的数量:

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_all(n_distinct)

# A tibble: 3 x 12
#    cyl  cars   mpg  disp    hp  drat    wt  qsec    vs    am  gear  carb
#  <dbl> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
#1     4    11     9    11    10    10    11    11     2     2     3     2
#2     6     7     6     5     4     5     6     7     2     2     3     3
#3     8    14    12    11     9    11    13    14     1     2     2     4

请注意,我们只需要添加 group_by 语句,其余代码是相同的。输出现在由三行组成 - 一个用于 cyl 的每个唯一值。

summarise 特定的多列,请使用 summarise_at

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_at(c("mpg", "disp", "hp"), mean)

# A tibble: 3 x 4
#    cyl      mpg     disp        hp
#  <dbl>    <dbl>    <dbl>     <dbl>
#1     4 26.66364 105.1364  82.63636
#2     6 19.74286 183.3143 122.28571
#3     8 15.10000 353.1000 209.21429

可以使用 helper 函数(?select_helpers)代替列名来选择特定列

要应用多个函数,请将函数名称作为字符向量传递:

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_at(c("mpg", "disp", "hp"), 
                 c("mean", "sd"))

或将它们包装在 funs 中:

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_at(c("mpg", "disp", "hp"), 
                 funs(mean, sd))

# A tibble: 3 x 7
#    cyl mpg_mean disp_mean   hp_mean   mpg_sd  disp_sd    hp_sd
#  <dbl>    <dbl>     <dbl>     <dbl>    <dbl>    <dbl>    <dbl>
#1     4 26.66364  105.1364  82.63636 4.509828 26.87159 20.93453
#2     6 19.74286  183.3143 122.28571 1.453567 41.56246 24.26049
#3     8 15.10000  353.1000 209.21429 2.560048 67.77132 50.97689

现在,列名称附加了函数名称以使它们保持不同。要更改此设置,请传递要附加功能的名称:

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_at(c("mpg", "disp", "hp"), 
                 c(Mean = "mean", SD = "sd"))

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_at(c("mpg", "disp", "hp"), 
                 funs(Mean = mean, SD = sd))

# A tibble: 3 x 7
#    cyl mpg_Mean disp_Mean   hp_Mean   mpg_SD  disp_SD    hp_SD
#  <dbl>    <dbl>     <dbl>     <dbl>    <dbl>    <dbl>    <dbl>
#1     4 26.66364  105.1364  82.63636 4.509828 26.87159 20.93453
#2     6 19.74286  183.3143 122.28571 1.453567 41.56246 24.26049
#3     8 15.10000  353.1000 209.21429 2.560048 67.77132 50.97689

要有条件地选择列,请使用 summarise_if

cyl 所有列的 numeric 中的 mean

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_if(is.numeric, mean) 

# A tibble: 3 x 11
#    cyl      mpg     disp        hp     drat       wt     qsec
#  <dbl>    <dbl>    <dbl>     <dbl>    <dbl>    <dbl>    <dbl>
#1     4 26.66364 105.1364  82.63636 4.070909 2.285727 19.13727
#2     6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714
#3     8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214
# ... with 4 more variables: vs <dbl>, am <dbl>, gear <dbl>,
#   carb <dbl>

然而,一些变量是离散的,并且这些变量的 mean 没有意义。

通过 cyl 获取仅连续变量的 mean

mtcars_tbl %>% 
    group_by(cyl) %>% 
    summarise_if(function(x) is.numeric(x) & n_distinct(x) > 6, mean)

# A tibble: 3 x 7
#    cyl      mpg     disp        hp     drat       wt     qsec
#  <dbl>    <dbl>    <dbl>     <dbl>    <dbl>    <dbl>    <dbl>
#1     4 26.66364 105.1364  82.63636 4.070909 2.285727 19.13727
#2     6 19.74286 183.3143 122.28571 3.585714 3.117143 17.97714
#3     8 15.10000 353.1000 209.21429 3.229286 3.999214 16.77214