R语言数据分析(五)

R语言数据分析(五)


文章目录

  • R语言数据分析(五)
  • 前言
  • 一、什么是整洁的数据
  • 二、延长数据
    • 2.1 列名中的数据值
    • 2.2 `pivot_longer()`的处理原理
    • 2.3 列名中包含许多变量的情况
    • 2.4 列名同时包含数据和变量
  • 三、扩宽数据
    • 3.1 `pivot_wider`的处理原理
  • 总结


前言

我们学习了数据导入、可视化以及数据转换的相关知识,那么在数据导入后要进行的就是数据的整理,这是一个将凌乱的数据整理成为整洁数据的过程。只有整洁的数据才能很好的进行数据转换分析以及可视化。在这一节的学习中我们将会使用一种称为tidy data的系统在R中组织数据。(注意加载tidyverse包)

一、什么是整洁的数据

数据的呈现方式多种多样,下面的示例展示了三种不同的方式整理的相同的数据。每个数据都用于显示一组数据,包括:英雄名称、版本、攻击力和防御力数值,但每个数据集组织这些值的方式不同:

# 这里是我自定义的table1、2、3,可以自己去自定义一些tibble顺便复习前面的知识了,其实在tidyverse中也有自己的table1、2、3存在,可以自行查看。
table1
#> # A tibble: 6 × 4
#>   Hero  Version   ATK   DEF
#>   <chr>   <dbl> <dbl> <dbl>
#> 1 LMY         1   999 666  
#> 2 LMY         2  1000 999  
#> 3 NEW         1    99  66  
#> 4 NEW         2   100  99  
#> 5 Z           1     5   1  
#> 6 Z           2     5   0.5table2
#> # A tibble: 12 × 4
#>    Hero  Version type   value
#>    <chr>   <dbl> <chr>  <dbl>
#>  1 LMY         1 ATK    999  
#>  2 LMY         1 DEF    666  
#>  3 LMY         2 ATK   1000  
#>  4 LMY         2 DEF    999  
#>  5 NEW         1 ATK     99  
#>  6 NEW         1 DEF    100  
#>  7 NEW         2 ATK     66  
#>  8 NEW         2 DEF     99  
#>  9 Z           1 ATK      5  
#> 10 Z           1 DEF      5  
#> 11 Z           2 ATK      1  
#> 12 Z           2 DEF      0.5table3
#> # A tibble: 6 × 3
#>   Hero  Version  rate
#>   <chr>   <dbl> <dbl>
#> 1 LMY         1 1.5  
#> 2 LMY         2 1.00 
#> 3 NEW         1 0.99 
#> 4 NEW         2 0.667
#> 5 Z           1 1    
#> 6 Z           2 2

其中table1是在tidyverse中容易使用的形式,以为它是tidy的。

整洁的数据集需要遵循三个相互关联的规则:

  1. 每个变量都是一列,每一列都是一个变量。

  2. 每个观测值都是一行,每一行都是一个观测值。

  3. 每个值都是一个单元格,每个单元格都是一个值。

保持数据的整洁主要有两个优点:

  1. 一致的数据存储方式有一个普遍的优势。更易于学习工具,具有底层的一致性

  2. 变量放在列中有一个特定的优势,以为它很贴合R的矢量化性质。

tidyverse中所有软件包都旨在处理整洁的数据,下面是一些小示例:

table1 |> mutate(rate = ATK / DEF)
#> # A tibble: 6 × 5
#>   Hero  Version   ATK   DEF  rate
#>   <chr>   <dbl> <dbl> <dbl> <dbl>
#> 1 LMY         1   999 666    1.5 
#> 2 LMY         2  1000 999    1.00
#> 3 NEW         1    99  66    1.5 
#> 4 NEW         2   100  99    1.01
#> 5 Z           1     5   1    5   
#> 6 Z           2     5   0.5 10table1 |> group_by(Version) |> summarize(total_version = sum(ATK))
#> # A tibble: 2 × 2
#>   Version total_version
#>     <dbl>         <dbl>
#> 1       1          1103
#> 2       2          1105ggplot(table1, aes(x = Version, y = ATK)) +geom_line(aes(group = Hero), color = "Blue") + geom_point(aes(color = Hero, shape = Hero)) +scale_x_continuous(breaks = c(1.0, 2.0))

在这里插入图片描述

二、延长数据

整洁数据的原则看起来十分简单,但是在大多数情况下,遇到的数据都是不整洁的。这就意味着大多数实际分析至少需要一点整理。

首先要弄清楚基础变量和观察值是什么。接下来,要将数据转化为整洁的形式,列包含变量,行包含观测值。

2.1 列名中的数据值

tidyverse中的billboard数据集记录了2000年歌曲广告排名:

billboard
#> # A tibble: 317 × 79
#>    artist     track date.entered   wk1   wk2   wk3   wk4   wk5   wk6   wk7   wk8
#>    <chr>      <chr> <date>       <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#>  1 2 Pac      Baby… 2000-02-26      87    82    72    77    87    94    99    NA
#>  2 2Ge+her    The … 2000-09-02      91    87    92    NA    NA    NA    NA    NA
#>  3 3 Doors D… Kryp… 2000-04-08      81    70    68    67    66    57    54    53
#>  4 3 Doors D… Loser 2000-10-21      76    76    72    69    67    65    55    59
#>  5 504 Boyz   Wobb… 2000-04-15      57    34    25    17    17    31    36    49
#>  6 98^0       Give… 2000-08-19      51    39    34    26    26    19     2     2
#>  7 A*Teens    Danc… 2000-07-08      97    97    96    95   100    NA    NA    NA
#>  8 Aaliyah    I Do… 2000-01-29      84    62    51    41    38    35    35    38
#>  9 Aaliyah    Try … 2000-03-18      59    53    38    28    21    18    16    14
#> 10 Adams, Yo… Open… 2000-08-26      76    76    74    69    68    67    61    58
#> # ℹ 307 more rows
#> # ℹ 68 more variables: wk9 <dbl>, wk10 <dbl>, wk11 <dbl>, wk12 <dbl>,
#> #   wk13 <dbl>, wk14 <dbl>, wk15 <dbl>, wk16 <dbl>, wk17 <dbl>, wk18 <dbl>,
#> #   wk19 <dbl>, wk20 <dbl>, wk21 <dbl>, wk22 <dbl>, wk23 <dbl>, wk24 <dbl>,
#> #   wk25 <dbl>, wk26 <dbl>, wk27 <dbl>, wk28 <dbl>, wk29 <dbl>, wk30 <dbl>,
#> #   wk31 <dbl>, wk32 <dbl>, wk33 <dbl>, wk34 <dbl>, wk35 <dbl>, wk36 <dbl>,
#> #   wk37 <dbl>, wk38 <dbl>, wk39 <dbl>, wk40 <dbl>, wk41 <dbl>, wk42 <dbl>, …

其中,每个观测值是一首歌,前三列是歌曲信息,之后有76列来描述歌曲每周的排名。这76列中,列名是一个变量(week),单元格值是另一个变量(week rank)。

为了整理这些数据,我们使用pivot_longer()函数:

billboard |> pivot_longer(cols = starts_with("wk"),names_to = "week",values_to = "rank")
#> # A tibble: 24,092 × 5
#>    artist track                   date.entered week   rank
#>    <chr>  <chr>                   <date>       <chr> <dbl>
#>  1 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk1      87
#>  2 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk2      82
#>  3 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk3      72
#>  4 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk4      77
#>  5 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk5      87
#>  6 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk6      94
#>  7 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk7      99
#>  8 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk8      NA
#>  9 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk9      NA
#> 10 2 Pac  Baby Don't Cry (Keep... 2000-02-26   wk10     NA
#> # ℹ 24,082 more rows

使用此函数需要注意:

  • cols参数用于指定哪些列需要进行整合,这个参数使用的语法与select()相同,因此可以使用!c(artist, track, data.entered)或者starts_with("wk")

  • names_to参数对存储在列名中的变量进行命名。

  • values_to参数将存储在单元格中的变量进行命名。

我们注意到转化后的数据中有NA值。比如数据的第8行就存在。这是因为这首歌在第8周并未进入前100名所导致的。那么这些NA并不是真正的观察结果。因此可以使用参数values_drop_na = TRUE来使得pivot_longer()删除NA

现在数据就是整洁的了,不过我们可以通过使用mutate()readr::parse_number()来将字符串变为数字,parse_number()函数将从字符串提取第一个数字,忽略所有其他文本:

billboard_longer <- billboard |> pivot_longer(cols = starts_with("wk"),names_to = "week",values_to = "rank",values_drop_na = TRUE) |> mutate(week = parse_number(week))
billboard_longer
#> # A tibble: 5,307 × 5
#>    artist  track                   date.entered  week  rank
#>    <chr>   <chr>                   <date>       <dbl> <dbl>
#>  1 2 Pac   Baby Don't Cry (Keep... 2000-02-26       1    87
#>  2 2 Pac   Baby Don't Cry (Keep... 2000-02-26       2    82
#>  3 2 Pac   Baby Don't Cry (Keep... 2000-02-26       3    72
#>  4 2 Pac   Baby Don't Cry (Keep... 2000-02-26       4    77
#>  5 2 Pac   Baby Don't Cry (Keep... 2000-02-26       5    87
#>  6 2 Pac   Baby Don't Cry (Keep... 2000-02-26       6    94
#>  7 2 Pac   Baby Don't Cry (Keep... 2000-02-26       7    99
#>  8 2Ge+her The Hardest Part Of ... 2000-09-02       1    91
#>  9 2Ge+her The Hardest Part Of ... 2000-09-02       2    87
#> 10 2Ge+her The Hardest Part Of ... 2000-09-02       3    92
#> # ℹ 5,297 more rows

现在我们就可以对这样的结果进行很好的可视化了

billboard_longer |> ggplot(aes(x = week, y = rank, group = track)) + geom_line(alpha = 0.1) +scale_y_reverse()

在这里插入图片描述

2.2 pivot_longer()的处理原理

明白使用函数pivot_longer()处理的原理很重要,这样我们就能够在需要使用这些功能的时候能更快的想到该函数。

假设我们有三个小朋友,记为A、B、C。两年分别测量了两次身高。我们建立一个tibble表格来记录数据:

df <- tribble(~id, ~h1, ~h2,"A", 110, 130,"B", 100, 110,"C", 80, 135
)

我们经过处理后得到以下数据集:

df |> pivot_longer(cols = h1:h2,names_to = "year_h",values_to = "value")
#> # A tibble: 6 × 3
#>   id    year_h value
#>   <chr> <chr>  <dbl>
#> 1 A     h1       110
#> 2 A     h2       130
#> 3 B     h1       100
#> 4 B     h2       110
#> 5 C     h1        80
#> 6 C     h2       135

函数如何工作的呢?逐列来看,我们发现了其工作模式。如下图所示:

在这里插入图片描述

  1. 已有的列重复了cols参数中列数的次数

  2. cols参数中的列名重复了行数的次数

  3. cols参数中列的值从上到下从左到右依次进行排列

2.3 列名中包含许多变量的情况

有时列名可能包含许多信息。比如,在who2上可以看到WHO发布的关于结核病诊断的信息:

who2
#> # A tibble: 7,240 × 58
#>    country      year sp_m_014 sp_m_1524 sp_m_2534 sp_m_3544 sp_m_4554 sp_m_5564
#>    <chr>       <dbl>    <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>
#>  1 Afghanistan  1980       NA        NA        NA        NA        NA        NA
#>  2 Afghanistan  1981       NA        NA        NA        NA        NA        NA
#>  3 Afghanistan  1982       NA        NA        NA        NA        NA        NA
#>  4 Afghanistan  1983       NA        NA        NA        NA        NA        NA
#>  5 Afghanistan  1984       NA        NA        NA        NA        NA        NA
#>  6 Afghanistan  1985       NA        NA        NA        NA        NA        NA
#>  7 Afghanistan  1986       NA        NA        NA        NA        NA        NA
#>  8 Afghanistan  1987       NA        NA        NA        NA        NA        NA
#>  9 Afghanistan  1988       NA        NA        NA        NA        NA        NA
#> 10 Afghanistan  1989       NA        NA        NA        NA        NA        NA
#> # ℹ 7,230 more rows
#> # ℹ 50 more variables: sp_m_65 <dbl>, sp_f_014 <dbl>, sp_f_1524 <dbl>,
#> #   sp_f_2534 <dbl>, sp_f_3544 <dbl>, sp_f_4554 <dbl>, sp_f_5564 <dbl>,
#> #   sp_f_65 <dbl>, sn_m_014 <dbl>, sn_m_1524 <dbl>, sn_m_2534 <dbl>,
#> #   sn_m_3544 <dbl>, sn_m_4554 <dbl>, sn_m_5564 <dbl>, sn_m_65 <dbl>,
#> #   sn_f_014 <dbl>, sn_f_1524 <dbl>, sn_f_2534 <dbl>, sn_f_3544 <dbl>,
#> #   sn_f_4554 <dbl>, sn_f_5564 <dbl>, sn_f_65 <dbl>, ep_m_014 <dbl>, …

除了country和year列外,剩下56列命名格式统一,由三部分组成分别是诊断方法、性别和年龄范围,用_分隔。这种情况下记录了6条消息。我们可以使用pivot_longer将其分开:

who2 |> pivot_longer(cols = !(country:year),names_to = c("diagnosis","gender", "age"),names_sep = "_",values_to = "count")
#> # A tibble: 405,440 × 6
#>    country      year diagnosis gender age   count
#>    <chr>       <dbl> <chr>     <chr>  <chr> <dbl>
#>  1 Afghanistan  1980 sp        m      014      NA
#>  2 Afghanistan  1980 sp        m      1524     NA
#>  3 Afghanistan  1980 sp        m      2534     NA
#>  4 Afghanistan  1980 sp        m      3544     NA
#>  5 Afghanistan  1980 sp        m      4554     NA
#>  6 Afghanistan  1980 sp        m      5564     NA
#>  7 Afghanistan  1980 sp        m      65       NA
#>  8 Afghanistan  1980 sp        f      014      NA
#>  9 Afghanistan  1980 sp        f      1524     NA
#> 10 Afghanistan  1980 sp        f      2534     NA
#> # ℹ 405,430 more rows

另外还有一种方法可以替代names_sep就是names_pattern,这需要用到正则表达式来提取变量,我们后续在逐步介绍。

从原理上来看,他是将原来names_to参数使用的列排列完之后,又按照names_sep的规则进行了分列。

2.4 列名同时包含数据和变量

有些更复杂的数据集,其列名同时包含了数据和变量。比如:

household
#> # A tibble: 5 × 5
#>   family dob_child1 dob_child2 name_child1 name_child2
#>    <int> <date>     <date>     <chr>       <chr>      
#> 1      1 1998-11-26 2000-01-29 Susan       Jose       
#> 2      2 1996-06-22 NA         Mark        <NA>       
#> 3      3 2002-07-11 2004-04-05 Sam         Seth       
#> 4      4 2004-10-10 2009-08-27 Craig       Khai       
#> 5      5 2000-12-05 2005-02-28 Parker      Gracie

这里记录了5个家庭数据,其中最多包含两个孩子的姓名及出生日期。这个数据集的列名中包含了两个变量的名称(namedob),以及另一个变量的值(child的值12)。此时想要解决这个问题,names_to会使用特殊的".value"作为值的指示,而不是新列名,这样会覆盖掉values_to的参数:

household |> pivot_longer(cols = !family,names_to = c(".value", "child"),names_sep = "_",values_drop_na = TRUE)
#> # A tibble: 9 × 4
#>   family child  dob        name  
#>    <int> <chr>  <date>     <chr> 
#> 1      1 child1 1998-11-26 Susan 
#> 2      1 child2 2000-01-29 Jose  
#> 3      2 child1 1996-06-22 Mark  
#> 4      3 child1 2002-07-11 Sam   
#> 5      3 child2 2004-04-05 Seth  
#> 6      4 child1 2004-10-10 Craig 
#> 7      4 child2 2009-08-27 Khai  
#> 8      5 child1 2000-12-05 Parker
#> 9      5 child2 2005-02-28 Gracie

具体情况就像上面这样,一目了然。

三、扩宽数据

有时一个观测值的指标可能分布在多行中,这时我们就可以通过增加列和减少行的方法来扩宽数据集。使用到的函数是pivot_wider。比如下面的数据集:

cms_patient_experience
#> # A tibble: 500 × 5
#>    org_pac_id org_nm                           measure_cd measure_title prf_rate
#>    <chr>      <chr>                            <chr>      <chr>            <dbl>
#>  1 0446157747 USC CARE MEDICAL GROUP INC       CAHPS_GRP… CAHPS for MI…       63
#>  2 0446157747 USC CARE MEDICAL GROUP INC       CAHPS_GRP… CAHPS for MI…       87
#>  3 0446157747 USC CARE MEDICAL GROUP INC       CAHPS_GRP… CAHPS for MI…       86
#>  4 0446157747 USC CARE MEDICAL GROUP INC       CAHPS_GRP… CAHPS for MI…       57
#>  5 0446157747 USC CARE MEDICAL GROUP INC       CAHPS_GRP… CAHPS for MI…       85
#>  6 0446157747 USC CARE MEDICAL GROUP INC       CAHPS_GRP… CAHPS for MI…       24
#>  7 0446162697 ASSOCIATION OF UNIVERSITY PHYSI… CAHPS_GRP… CAHPS for MI…       59
#>  8 0446162697 ASSOCIATION OF UNIVERSITY PHYSI… CAHPS_GRP… CAHPS for MI…       85
#>  9 0446162697 ASSOCIATION OF UNIVERSITY PHYSI… CAHPS_GRP… CAHPS for MI…       83
#> 10 0446162697 ASSOCIATION OF UNIVERSITY PHYSI… CAHPS_GRP… CAHPS for MI…       63
#> # ℹ 490 more rows

该数据集研究的目标是一个组织,但是每个组织的数据被分布在了6行中,调查组织中的每个测量值各占一行。我们可以看到:

cms_patient_experience |> distinct(measure_cd, measure_title)
#> # A tibble: 6 × 2
#>   measure_cd   measure_title                                                    
#>   <chr>        <chr>                                                            
#> 1 CAHPS_GRP_1  CAHPS for MIPS SSM: Getting Timely Care, Appointments, and Infor…
#> 2 CAHPS_GRP_2  CAHPS for MIPS SSM: How Well Providers Communicate               
#> 3 CAHPS_GRP_3  CAHPS for MIPS SSM: Patient's Rating of Provider                 
#> 4 CAHPS_GRP_5  CAHPS for MIPS SSM: Health Promotion and Education               
#> 5 CAHPS_GRP_8  CAHPS for MIPS SSM: Courteous and Helpful Office Staff           
#> 6 CAHPS_GRP_12 CAHPS for MIPS SSM: Stewardship of Patient Resources

这两列都不是很好的变量名,其中measure_cd并没有按时变量的含义,measure_tittle也只是包含一个长句子。现在,让我们使用measure_cd列作为我们新列名的源。创建一个新的数据集:

cms_patient_experience |> pivot_wider(names_from = measure_cd,values_from = prf_rate)
#> # A tibble: 500 × 9
#>    org_pac_id org_nm           measure_title CAHPS_GRP_1 CAHPS_GRP_2 CAHPS_GRP_3
#>    <chr>      <chr>            <chr>               <dbl>       <dbl>       <dbl>
#>  1 0446157747 USC CARE MEDICA… CAHPS for MI…          63          NA          NA
#>  2 0446157747 USC CARE MEDICA… CAHPS for MI…          NA          87          NA
#>  3 0446157747 USC CARE MEDICA… CAHPS for MI…          NA          NA          86
#>  4 0446157747 USC CARE MEDICA… CAHPS for MI…          NA          NA          NA
#>  5 0446157747 USC CARE MEDICA… CAHPS for MI…          NA          NA          NA
#>  6 0446157747 USC CARE MEDICA… CAHPS for MI…          NA          NA          NA
#>  7 0446162697 ASSOCIATION OF … CAHPS for MI…          59          NA          NA
#>  8 0446162697 ASSOCIATION OF … CAHPS for MI…          NA          85          NA
#>  9 0446162697 ASSOCIATION OF … CAHPS for MI…          NA          NA          83
#> 10 0446162697 ASSOCIATION OF … CAHPS for MI…          NA          NA          NA
#> # ℹ 490 more rows
#> # ℹ 3 more variables: CAHPS_GRP_5 <dbl>, CAHPS_GRP_8 <dbl>, CAHPS_GRP_12 <dbl>

不过现在看来,我们依然为每个组织设置了多行,这是因为我们并未给出哪一列具有唯一标识,可以这样给出:

cms_patient_experience |> pivot_wider(id_cols = starts_with("org"),names_from = measure_cd,values_from = prf_rate)
#> # A tibble: 95 × 8
#>    org_pac_id org_nm CAHPS_GRP_1 CAHPS_GRP_2 CAHPS_GRP_3 CAHPS_GRP_5 CAHPS_GRP_8
#>    <chr>      <chr>        <dbl>       <dbl>       <dbl>       <dbl>       <dbl>
#>  1 0446157747 USC C…          63          87          86          57          85
#>  2 0446162697 ASSOC…          59          85          83          63          88
#>  3 0547164295 BEAVE…          49          NA          75          44          73
#>  4 0749333730 CAPE …          67          84          85          65          82
#>  5 0840104360 ALLIA…          66          87          87          64          87
#>  6 0840109864 REX H…          73          87          84          67          91
#>  7 0840513552 SCL H…          58          83          76          58          78
#>  8 0941545784 GRITM…          46          86          81          54          NA
#>  9 1052612785 COMMU…          65          84          80          58          87
#> 10 1254237779 OUR L…          61          NA          NA          65          NA
#> # ℹ 85 more rows
#> # ℹ 1 more variable: CAHPS_GRP_12 <dbl>

3.1 pivot_wider的处理原理

我们还是举个前面类似的简单例子来探究处理原理:

df <- tribble(~id, ~year_h, ~value,"A", "h1", 100,"B", "h1", 90,"A", "h2", 130,"B", "h2", 110,"A", "h3", 132
)

使用pivot_wider时将会从value列中获取值,从year_h列中获取新列名:

df |> 
pivot_wider(names_from = year_h,values_from = value
)
#> # A tibble: 2 × 4
#>   id       h1    h2    h3
#>   <chr> <dbl> <dbl> <dbl>
#> 1 A       100   130   132
#> 2 B        90   110    NA

这个过程是怎么样的呢?首先pivot_wider()会弄清楚行和列中的内容,新列名就是year_h列中的唯一值:

df |> distinct(year_h) |> pull()
#> [1] "h1" "h2" "h3"

默认情况下,输出的行由所有不进入新名称或者值得变量确定,它们会被认作是id.cols,这个数据集只有一列,但通常可以有多列,也可以自行指定。

df |> select(-year_h, -value) |> distinct()
#> # A tibble: 2 × 1
#>   id   
#>   <chr>
#> 1 A    
#> 2 B

然后pivot_wider会将这些结果组合起来生成一个用NA填充的空数据:

df |> select(-year_h, -value) |> distinct() |> mutate(h1 = NA, h2 = NA, h3 = NA)
#> # A tibble: 2 × 4
#>   id    h1    h2    h3   
#>   <chr> <lgl> <lgl> <lgl>
#> 1 A     NA    NA    NA   
#> 2 B     NA    NA    NA

最后,pivot_wider会使用输入的数据来填充相应的位置。

如果存在多行对应一个输出的单元格会发生什么情况呢?此时在输出的数据中将会存在列内列表的结构:

df <- tribble(~id, ~year_h, ~value,"A", "h1", 100,"A", "h1", 90,"A", "h2", 130,"B", "h1", 110,"B", "h2", 132
)df |> pivot_wider(names_from = year_h,values_from = value)
#> Warning: Values from `value` are not uniquely identified; output will contain list-cols.
#> • Use `values_fn = list` to suppress this warning.
#> • Use `values_fn = {summary_fun}` to summarise duplicates.
#> • Use the following dplyr code to identify duplicates.
#>   {data} %>%
#>   dplyr::group_by(id, year_h) %>%
#>   dplyr::summarise(n = dplyr::n(), .groups = "drop") %>%
#>   dplyr::filter(n > 1L)
#> # A tibble: 2 × 3
#>   id    h1        h2       
#>   <chr> <list>    <list>   
#> 1 A     <dbl [2]> <dbl [1]>
#> 2 B     <dbl [1]> <dbl [1]>

可以通过警告信息中的提示来检查可能存在的问题:

df |> dplyr::group_by(id, year_h) |> dplyr::summarise(n = dplyr::n(), .groups = "drop") |> dplyr::filter(n > 1L)
#> # A tibble: 1 × 3
#>   id    year_h     n
#>   <chr> <chr>  <int>
#> 1 A     h1         2

总结

至此,我们快速学完了数据分析的全过程基础,已经可以应付很多的数据处理情况了。在这一节的学习中,我们学了数据的整理,这将帮助我们获得整洁的数据。另外,我们还学到了一些扩充数据的技巧,熟练掌握这些函数的使用将在我们以后实际遇到对应情况时,快速想到相应的解决措施。我们所有学习到的知识都应该在实践中将他们运用起来。(碎碎念:这几天虽然还在家房价,但都在帮老板干活,五天开了三次会,真累啊。但是学无止境,每天还是要完成一定的学习任务的。话说老板出差为什么不能带上我去玩呢?)

这个系列还未结束,后续将会就这些步骤展开更加详细的进阶介绍。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/697831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣226 翻转二叉树 Java版本

文章目录 题目描述解题思路代码 题目描述 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1] 示例 2&#xff1a; 输入&#xff1a;root…

[云原生] 二进制k8s集群(下)部署高可用master节点

在上一篇文章中&#xff0c;就已经完成了二进制k8s集群部署的搭建&#xff0c;但是单机master并不适用于企业的实际运用&#xff08;因为单机master中&#xff0c;仅仅只有一台master作为节点服务器的调度指挥&#xff0c;一旦宕机。就意味着整个集群的瘫痪&#xff0c;所以成熟…

这才开工没几天收到Offer了,简历改的好,找工作没烦恼。

喜报喜报 这才开工没几天&#xff0c;就收到了喜报&#xff01; 就像上面截图中所说的一样&#xff1a;简历改了真的有用。 我也和大家分享一下优化简历的技巧&#xff0c;希望对大家有帮助&#xff0c;把握住金三银四的机会&#xff0c;都能顺利上岸&#xff0c;升职加薪&am…

Leetcode日记 2583. 二叉树中的第 K 大层和

Leetcode日记 2583. 二叉树中的第 K 大层和 题目&#xff1a;解题思路&#xff1a;代码实现制作不易&#xff0c;感谢三连&#xff0c;谢谢啦 题目&#xff1a; 给你一棵二叉树的根节点 root 和一个正整数 k 。 树中的 层和 是指 同一层 上节点值的总和。 返回树中第 k 大的层和…

Vue2 基础面试题

v-show 和 v-if 区别 v-show 通过 CSS display 控制显示和隐藏v-if 通过判断组件真实渲染和销毁&#xff0c;而不是显示和隐藏频繁切换显示状态用 v-show&#xff0c;否则用 v-if v-if 当 v-if 与 v-for 一起使用时&#xff0c;v-for 具有比 v-if 更高的优先级&#xff0c;意…

PolarDN MISC做题笔记

cat flag 使用01打开flag.png,发现图片尾部有padding的数据。D0 CF 11 E0 A1 B1 1A E1为office2007以前版本的文件头。将其另存为flag.doc,打开发现提示需要密码。&#xff08;可以注意到&#xff1a;D0CF11E0非常类似DOCFILE&#xff09; 使用john的office2john.py 提取hash …

【操作系统】处理机调度算法

实验3 处理机管理 一、实验目的 在多道程序或多任务系统中&#xff0c;系统中同时处于就绪态的进程有若干个&#xff0c;即能运行的进程数远远大于处理机个数。为了使系统中的各个进程能有条不紊的运行&#xff0c;必须按照某种调度策略&#xff0c;选择一个进程占用处理机。…

SpringBoot指定外部环境配置

nohup java -Xms256m -Xmx512m -Dfile.encodingUTF-8 -jar /usr/local/xxxx.jar --spring.profiles.activeprod > system.log 2>&1 & --spring.profiles.activeprod修改的是多环境配置中内部application.properties里的spring.profiles.active值 -Dspring.config…

消息队列MQ 保证消息不丢失(消息可靠性)

文章目录 概述RabbitMQ 怎么避免消息丢失&#xff08;可靠传输&#xff09;RocketMQ 怎么确保消息不丢失Kafka 怎么保证消息不丢失activeMQ 怎么避免消息丢失MQ 宕机了消息是否会丢失线上服务宕机时&#xff0c;如何保证数据100%不丢失吗&#xff1f;消息队列消息持久化 概述 …

思伟老友记 | 携手并进17年 中泰公司的稳步发展和企业传承

17年携手并进 合作共赢 2023年是中泰&#xff08;福建&#xff09;混凝土发展有限公司携手思伟软件的第17年。在这关键的17年间&#xff0c;我们共同经历了一个行业的兴盛发展&#xff0c;也相互见证了彼此的荣耀成长。中泰从泉州惠安洛阳江边一个简单的搅拌站&#xff0c;到如…

h-table(表格列表组件的全封装)

文章目录 概要h-table的封装过程查询组件封装 h-highForm结果页右侧工具栏封装RightToolbar结果页列表组件h-table结果页vue页面使用js文件有需要的请私信博主&#xff0c;还请麻烦给个关注&#xff0c;博主不定期更新组件封装&#xff0c;或许能够有所帮助&#xff01;&#x…

如何做代币分析:以 SOL 币为例

作者&#xff1a;lesleyfootprint.network 编译&#xff1a;cicifootprint.network 数据源&#xff1a;Solana Token Dashboard &#xff08;仅包括以太坊数据&#xff09; 在加密货币和数字资产领域&#xff0c;代币分析起着至关重要的作用。代币分析指的是深入研究与代币…

springmvc基于springboot 的音乐播放系统 _7sdu8

这就意味着音乐播放系统的设计可以比其他系统更为出色的能力&#xff0c;可以更高效的完成最新的ymj排行榜、ymj音乐资讯等功能。 此系统设计主要采用的是JAVA语言来进行开发&#xff0c;JSP技术、采用SSM框架技术&#xff0c;框架分为三层&#xff0c;分别是控制层Controller&…

vue3 vuex

目录 Vuex 是什么 什么是“状态管理模式”&#xff1f; 什么情况下我应该使用 Vuex&#xff1f; 使用方法&#xff1a; 提交载荷&#xff08;Payload&#xff09; 对象风格的提交方式 使用常量替代 Mutation 事件类型 Mutation 必须是同步函数 在组件中提交 Mutation …

redis GEO 类型原理及命令详解

目录 前言 一、GeoHash 的编码方法 二、Redis 操作GEO类型 前言 我们有一个需求是用户搜索附近的店铺&#xff0c;就是所谓的位置信息服务&#xff08;Location-Based Service&#xff0c;LBS&#xff09;的应用。这样的相关服务我们每天都在接触&#xff0c;用滴滴打车&am…

使用ENV工具编译RT-Thread【详细过程讲解:从下载到编译、设置】

感兴趣的宝子&#xff0c;可以点个赞收藏&#xff0c;便于后期有需要的时候能快速找到~~ ENV编译编译RT-Thread工程的详细过程讲解 ENV简介ENV的下载设置ENV使用ENV编译RT-Thread工程◆ 打开ENV◆ 输入打包命令◆ 查看并打开工程文件◆ 使用menuconfig 对生成项目的RT-Thread配…

【Git企业实战开发】Git常用开发流操作总结

【Git企业实战开发】Git常用开发流操作总结 大家好 我是寸铁&#x1f44a; 总结了一篇Git常用开发流操作总结的文章✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 现在刚做项目的伙伴&#xff0c;可能你之前学过git&#xff0c;但是一实战发现不熟悉 没关系&#xff0c;看寸铁这篇…

【Linux】普通用户sudo失败怎么办

普通用户&#xff0c;sudo失败报错怎么办 问题分析如何解决成功 问题分析 新建的普通用户sudo失败 sudo提权&#xff0c;是以root的身份执行命令。 当我们用sudo提升权限的时候&#xff0c;这里有个问题&#xff0c;Linux会提示我们输入当前普通用户的密码——这就有点不好。…

【Linux取经路】基础I/O之重定向的实现原理

文章目录 一、再来理解重定向1.1 输出重定向效果演示1.2 重定向的原理1.3 dup21.4 输入重定向效果演示1.5 输入重定向代码实现 二、再来理解标准输出和标准错误2.1 同时对标准输出和标准错误进行重定向2.2 将标准输出和标准错误重定向到同一个文件 三、再看一切皆文件四、结语 …

Elasticsearch从入门到精通-01认识Elasticsearch

Elasticsearch从入门到精通-01认识Elasticsearch &#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是程序员行走的鱼 &#x1f342;博主从本篇正式开始ES学习&#xff0c;希望小伙伴可以一起探讨 &#x1f4d6; 本篇主要介绍和大家一块简单认识下ES并了解ES中的主要角色…