R语言数据分析(五)

news2024/11/14 13:31:24

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

总结

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

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

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

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

相关文章

uniapp微信小程序解决上方刘海屏遮挡

问题 在有刘海屏的手机上&#xff0c;我们的文字和按钮等可能会被遮挡 应该避免这种情况 解决 const SYSTEM_INFO uni.getSystemInfoSync();export const getStatusBarHeight ()> SYSTEM_INFO.statusBarHeight || 15;export const getTitleBarHeight ()>{if(uni.get…

k8s(2)

目录 一.二进制部署k8s 常见的K8S安装部署方式&#xff1a; k8s部署 二进制与高可用的区别 二.部署k8s 初始化操作&#xff1a; 每台node安装docker&#xff1a; 在 master01 节点上操作; 准备cfssl证书生成工具:&#xff1a; 执行脚本文件&#xff1a; 拉入etcd压缩包…

Spring Boot应用集成Actuator端点自定义Filter解决未授权访问的漏洞

一、前言 我们知道想要实时监控我们的应用程序的运行状态&#xff0c;比如实时显示一些指标数据&#xff0c;观察每时每刻访问的流量&#xff0c;或者是我们数据库的访问状态等等&#xff0c;需要使用到Actuator组件&#xff0c;但是Actuator有一个访问未授权问题&#xff0c;…

2023全新UI千月影视APP源码 | 前后端完美匹配、后端基于ThinkPHP框架

应用介绍 本文来自&#xff1a;2023全新UI千月影视APP源码 | 前后端完美匹配、后端基于ThinkPHP框架 - 源码1688 简介&#xff1a; 2023全新UI千月影视APP源码 | 前后端完美匹配、后端基于thinkphp框架 图片&#xff1a;

索引大战:探秘InnoDB数据库中B树和Hash索引的优劣

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 索引大战&#xff1a;探秘InnoDB数据库中B树和Hash索引的优劣 前言B树索引的深度解析Hash索引的奥秘揭晓性能对比分析 前言 在当今软件开发的世界中&#xff0c;数据库扮演着至关重要的角色。而InnoD…

怎么用sora赚第一桶金?

&#x1f31f;解锁文字变视频的强大功能&#xff01;&#x1f31f; ✨欢迎来到 Sora Cand&#xff0c;一个革命性的网站&#xff0c;利用 OpenAI 的 Sora 模型帮你把文字变成酷炫的视频&#xff01;✨ 想象一下&#xff0c;你的文字从纸上跳出来&#xff0c;变成引人入胜的视觉…

如何用IP地址找到实际位置?

在互联网世界中&#xff0c;每个设备都有一个独特的标识&#xff0c;那就是IP地址。它不仅是设备在网络中的“身份证”&#xff0c;还承载着设备在网络中的位置信息。那么&#xff0c;我们是否可以通过IP地址来找到设备的实际位置呢&#xff1f;本文将深入探讨这一问题。 一、I…

#11vue3中使用el-dialog展示与关闭交由父组件控制的写法

目录 1、法一&#xff1a;通过defineEmits调用父组件方法 1.1、父组件 1.2、子组件&#xff08;CONTENT&#xff09; 2、法二&#xff1a;通过difineExpose暴露子组件属性 2.1、父组件 2.2、子组件&#xff08;Child&#xff09; 1、法一&#xff1a;通过defineEmits调用…

【C语言】注释

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;C语言 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进步&…

vue3 toRefs之后的变量修改方法

上效果 修改值需要带上解构之前的对象名obj&#xff0c; changeName:()>{ // toRefs 解决后变量修改值方法&#xff1a; 解构前变量.字段新值 obj.name FEIFEI; } } 案例源码 <!DOCTYPE html> <html> <head><me…

算法——模拟

1. 什么是模拟算法&#xff1f; 官方一点来说 模拟算法&#xff08;Simulation Algorithm&#xff09;是一种通过模拟现实或抽象系统的运行过程来研究、分析或解决问题的方法。它通常涉及创建一个模型&#xff0c;模拟系统中的各种事件和过程&#xff0c;以便观察系统的行为&a…

从单体服务到微服务:多模式 Web 应用开发记录<一>背景全局变量优化

背景 最近在做一个事&#xff1a;下线一个超级大单体服务。单一统计代码行数其实不够全面&#xff0c;反正项目 git clone 下来文件就有这么大&#xff1a; 这是一个已经存在了十年以上的服务&#xff0c;随着业务的发展&#xff0c;这个服务已经无法满足我们的需求。 我们统…

胡夏爱意满满,浪漫尽显,心动不止。

♥ 为方便您进行讨论和分享&#xff0c;同时也为能带给您不一样的参与感。请您在阅读本文之前&#xff0c;点击一下“关注”&#xff0c;非常感谢您的支持&#xff01; 文 |猴哥聊娱乐 编 辑|徐 婷 校 对|侯欢庭 全网热议的胡夏暗恋文学&#xff0c;浪漫指数爆表&#xff01…

力扣382.链表随机节点

Problem: 382. 链表随机节点 文章目录 题目描述思路复杂度Code 题目描述 思路 由水塘抽样易得&#xff0c;当遇到i个元素&#xff0c;有 1 / i 1/i 1/i的概率选择该元素&#xff1b;则在实际操作中我们定义一个下标i从1开始遍历每次判断rand() % i 0&#xff08;该操作就是判断…

Verilog刷题笔记35

题目&#xff1a; Create a 1-bit wide, 256-to-1 multiplexer. The 256 inputs are all packed into a single 256-bit input vector. sel0 should select in[0], sel1 selects bits in[1], sel2 selects bits in[2], etc. 解法&#xff1a; module top_module( input [255:…

猜谜“龘”人速来!网安人元宵灯谜有礼了

​​灯笼高挂&#xff0c;星光璀璨&#xff0c;品味糯叽叽的元宵&#xff0c;以灯谜为媒&#xff0c;亚信安全邀你共赴元宵佳节。 热辣滚烫的班先别上了&#xff0c;文末有奖竞猜&#xff0c;快来参与&#xff01; 喜闹元宵 谜面一&#xff1a;一路向上成大业&#xff1b; 谜…

HTML5新婚、年会、各种聚会的现场抽奖活动(附源码)

文章目录 1.抽奖平台设计来源1.1 主界面效果1.2 抽奖效果1.3 中奖效果 2.效果和源码配置2.1 动态效果2.2 人员信息配置2.3 奖品信息配置2.4 抽奖音效配置2.5 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/deta…

第一节-docker介绍

这里写自定义目录标题 一、什么是docker二、docker和virtual machine三、docker架构 一、什么是docker docker是一种容器引擎&#xff0c;用于构建、部署、运行应用程序和服务。 docker的每个容器通过沙箱机制相互隔离&#xff0c;互不干扰。 docker容器技术相比传统的虚拟机有…

六、回归与聚类算法 - 模型保存与加载

目录 1、API 2、案例 欠拟合与过拟合线性回归的改进 - 岭回归分类算法&#xff1a;逻辑回归模型保存与加载无监督学习&#xff1a;K-means算法 1、API 2、案例

费舍尔FISHER金属探测器探测仪维修F70

美国FISHER LABS费舍尔地下金属探测器&#xff0c;金属探测仪等维修&#xff08;考古探金银铜探宝等仪器&#xff09;。 费舍尔F70视听目标ID金属探测器&#xff0c;Fisher 金属探测器公司成立于1931年&#xff0c;在实验条件很艰苦的情况下&#xff0c;研发出了地下金属探测器…