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.5

table2
#> # 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.5

table3
#> # 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 10

table1 |> 
  group_by(Version) |> 
  summarize(total_version = sum(ATK))
#> # A tibble: 2 × 2
#>   Version total_version
#>     <dbl>         <dbl>
#> 1       1          1103
#> 2       2          1105

ggplot(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

总结

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Electron实战之环境搭建

工欲善其事必先利其器&#xff0c;在进行实战开发的时候&#xff0c;我们最终的步骤是搞好一个舒服的开发环境&#xff0c;目前支持 Vue 的 Electron 工程化工具主要有 electron-vue、Vue CLI Plugin Electron Builder、electron-vite。 接下来我们将分别介绍基于 Vue CLI Plu…

查询数据库的编码集Oracle,MySQL

1、查询数据库的编码集Oracle,MySQL 1.1、oracle select * from v$nls_parameters where parameterNLS_CHARACTERSET; 查询版本&#xff1a;SELECT * FROM v$version 2、MySQL编码集 SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SC…

隐私也要付费?Meta公司为收集用户数据再出“奇招”

Cybernews网站消息&#xff0c;有相关人士表示&#xff0c;如果欧洲数据保护委员会&#xff08;EDPB&#xff09;不明确指出Meta公司的“付费或同意”的模式违反了欧盟的隐私法规&#xff0c;那么这一模式很可能会被大规模复制&#xff0c;危及数百万欧洲公民的自由选择权。 自…

Jenkins2.426邮件通知配置

之前安装的jenkins出现问题了&#xff0c;重新装了jenkins&#xff0c;需要重新配置&#xff1a;Maven&#xff0c;JDK&#xff0c;Allure报告&#xff0c;邮件通知&#xff0c;Extended E-mail Notification等 配置Maven&#xff0c;JDK参考&#xff1a;CICD集合(四):Jenkins…

排序第三篇 直接插入排序

插入排序的基本思想是&#xff1a; 每次将一个待排序的记录按其关键字的大小插入到前面已排好序的文件中的适当位置&#xff0c; 直到全部记录插入完为止。 一 简介 插入排序可分为2类 本文介绍 直接插入排序 它的基本操作是&#xff1a; 假设待排充序的记录存储在数组 R[1……

2.22 Qt day3 多界面跳转+qss登录界面优化+发布软件+对话框

思维导图&#xff1a; 完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号…

我们在SqlSugar开发框架中,用到的一些设计模式

我们在《SqlSugar开发框架》中&#xff0c;有时候都会根据一些需要引入一些设计模式&#xff0c;主要的目的是为了解决问题提供便利和代码重用等目的。而不是为用而用&#xff0c;我们的目的是解决问题&#xff0c;并在一定的场景下以水到渠成的方式处理。不过引入任何的设计模…

【教3妹学编程-算法题】匹配模式数组的子数组数目 I

3妹&#xff1a;2哥2哥&#xff0c;你有没有看到上海女老师出轨男学生的瓜啊。 2哥 : 看到 了&#xff0c;真的是太毁三观了&#xff01; 3妹&#xff1a;是啊&#xff0c; 老师本是教书育人的职业&#xff0c;明确规定不能和学生谈恋爱啊&#xff0c;更何况是出轨。 2哥 : 是啊…

HarmonyOS—LocalStorage:页面级UI状态存储

LocalStorage是页面级的UI状态存储&#xff0c;通过Entry装饰器接收的参数可以在页面内共享同一个LocalStorage实例。LocalStorage也可以在UIAbility实例内&#xff0c;在页面间共享状态。 本文仅介绍LocalStorage使用场景和相关的装饰器&#xff1a;LocalStorageProp和LocalS…

大保司保费贵,是否物有所值?

《大保司保费贵&#xff0c;是否物有所值》 这是罗师兄的原创文章 预计8-9分钟读完 作者&#xff1a;罗师兄 微信号&#xff1a;luoyun515 当我们想要买一份重疾险、储蓄险等长期险时&#xff0c; 我们会发现&#xff0c;同样的保障责任和保额&#xff0c; 不同保险公司的…

mac苹果电脑系统最好用的清理软件CleanMyMac2024功能介绍及如何激活解锁许可证

CleanMyMac X的界面设计简洁大气&#xff0c;为用户提供了直观且易于操作的使用体验。 布局清晰&#xff1a;界面布局非常明朗&#xff0c;左侧是功能栏&#xff0c;右侧则是信息界面。这种布局方式使得用户能够迅速找到所需的功能选项&#xff0c;提高了操作效率。色彩搭配&a…

Flutter常用命令,持续更新

目录 前言 Flutter 常用命令 Dart 常用命令 adb 常用命令&#xff08;用于 Android 开发&#xff09; 前言 当在开发Flutter项目时&#xff0c;熟悉一些常用的命令是非常重要的。这些命令可以帮助你执行各种任务&#xff0c;从构建应用程序到调试和测试。以下是一些Flutte…

亿道丨三防平板丨加固平板丨三防加固平板丨改善资产管理

库存资产管理中最重要的部分之一是准确性&#xff1b;过时的库存管理技术会增加运输过程中人为错误、物品丢失或纸张损坏的风险。如今随着三防平板电脑的广泛使用&#xff0c;库存管理也迎来了好帮手&#xff0c;通过使用三防平板电脑能够确保库存管理、数据存储和记录保存的准…

Hive【内部表、外部表、临时表、分区表、分桶表】【总结】

目录 Hive的物种表结构特性 一、内部表 建表 使用场景 二、外部表 建表:关键词【EXTERNAL】 场景&#xff1a; 外部表与内部表可互相转换 三、临时表 建表 临时表横向对比​编辑 四、分区表 建表&#xff1a;关键字【PARTITIONED BY】 场景&#xff1a; 五、分桶表 …

pip安装依赖环境出现的问题

一、error: subprocess-exited-with-error! 1、前期一直百度的错误如标题所示&#xff0c;得到的方案如下&#xff1a;&#xff08;但没解决问题&#xff09; &#xff08;1&#xff09;升级setuptools库&#xff0c;或者降低固定版本 //升级setuptools库&#xff0c;或者降低…

Spark之【基础介绍】

Spark最初是由美国伯克利大学AMP实验室在2009年开发&#xff0c;Spark时基于内存计算的大数据并行计算框架&#xff0c;可以用于构建大型的、低延迟的数据分析应用程序。 Spark是当今大数据领域最活跃、最热门、最高效的大数据通用计算平台之一。 Spark的特点 运行速度快 &am…

L2 清点代码库----PTA(疑问)

上图转自新浪微博&#xff1a;“阿里代码库有几亿行代码&#xff0c;但其中有很多功能重复的代码&#xff0c;比如单单快排就被重写了几百遍。请设计一个程序&#xff0c;能够将代码库中所有功能重复的代码找出。各位大佬有啥想法&#xff0c;我当时就懵了&#xff0c;然后就挂…

用Python插入页码到PDF文档

页码是许多类型文件中的重要内容&#xff0c;它能方便读者在文档中的导航。在创建PDF文档时&#xff0c;添加页码对于组织和引用内容特别有用。在本文中&#xff0c;我们将探讨如何利用Python程序高效地插入页码到PDF文档中&#xff0c;简化工作流程并创建出精美、结构合理的PD…

【selenium】执行 Javascript 脚本 滚动、元素的特殊操作等

某些特殊情况下&#xff0c;使用selenium的api无法操作页面元素&#xff0c;点击、滚动实现的某些功能&#xff0c;可以考虑通过执行js来完成。 为什么不用js写自动化&#xff1f;——selenium第一版是js写的&#xff0c;但js兼容性存在问题&#xff0c;所以引入webdriver 现在…