搜索
查看: 193|回复: 0

[R] R for data science 笔记--数据清洁

[复制链接]

1

主题

1

帖子

34

积分

新手上路

Rank: 1

积分
34
发表于 2018-10-11 10:29:08 | 显示全部楼层 |阅读模式
有三个相互关联的规则使数据集整洁:

每个变量都必须有自己的列。
每个观察必须有自己的行。
每个值必须有自己的单元格。

简单来说就是:
将每个数据集放在一个tibble中。
将每个变量放在一列中。(列:变量值;行:观测值)

dplyr,ggplot2和tidyverse中的所有其他软件包都设计用于处理整洁的数据。

12.2练习
1.Using prose,describe how the variables and observations are organized in each of the sampletables.
table1每一行是一个(国家,年)与变量cases和population
table2,每行是country,year,variable(“cases”,“population”)组合,并且有一个count变量带有变量的数值
table3,每行是(国家,年)组合,其中列rate具有作为格式中的字符串的种群率"cases/rate"
table4a表示案例,而table4b表是人口表。在每个表中,每行是一个国家/地区,每列是一年,单元格是表的变量值。

2.按要求修改table2和4
Table2:
(t2_case_1 <-table2 %>%
  filter(type == "cases")%>%
  rename(cases = count)%>%
  arrange(country,year))
(t2_population_1<- table2 %>%
    filter(type =="population")%>%
    rename(population = count)%>%
    arrange(country,year))
(t2_cases_per_cap_1<- t2_case_1 %>%
    mutate(population =t2_population_1$population)%>%
    mutate(cases_per_cap =(cases/population)*10000)%>%
    arrange(country,year)%>%
    select(country,year,cases_per_cap))
(t2_4 <-t2_cases_per_cap_1%>%
    mutate(type ="cases_per_cap")%>%
    rename(count = cases_per_cap))
(t2_4_total <-bind_rows(table2,t2_4)%>%
    arrange(country, year))
Table4:
table4c <-
  tibble(country = table4a$country,
         `1999` = table4a[["1999"]] /table4b[["1999"]] * 10000,
         `2000` = table4a[["2000"]] /table4b[["2000"]] * 10000)
table4c

3.Re-create the plot showing change incases over time using table2 instead of table1. What do you need to do first?
使用table1:
ggplot(table1,aes(year, cases)) +
  geom_line(aes(group = country), colour ="grey50") +
  geom_point(aes(colour = country))
使用table2:
table2 %>%
  filter(type == "cases") %>%
  ggplot(aes(year,count)) +
  geom_line(aes(group = country), colour = "grey50") +
  geom_point(aes(colour = country)) +
  scale_x_continuous(breaks = unique(table2$year)) +
  ylab("cases")


数据重构:gather()和spread()

file:////Users/zhaojing/Library/Group%20Containers/UBF8T346G9.Office/TemporaryItems/msohtmlclip/E47DAD68-CEDA-4B4A-9EDC-7C7DD37DE7D9.png
tidy4a <- table4a %>%
  gather(`1999`, `2000`, key = "year", value = "cases")
tidy4b <- table4b %>%
  gather(`1999`, `2000`, key = "year", value = "population")
left_join(tidy4a, tidy4b) ### left/right 都是一样的结果

file:////Users/zhaojing/Library/Group%20Containers/UBF8T346G9.Office/TemporaryItems/msohtmlclip/17221A82-D8D2-9B46-9555-F4BC8E1A6FE3.png
table2 %>% spread(key = type,value = count)

12.3练习

1.
gather()而spread()不是完全对称的
因为gather()和spread()列的类型在它们之间传送不是完全对称的。
当gather()在数据框上使用时,它会丢弃有关原始列类型的所有信息。此外,它必须强制收集到单个类型的所有变量,因为它们将进入单个向量。稍后如果再spread()那个数据框,该spread()函数无法知道之前收集的列的原始数据类型是什么。

在此示例中,在原始表中year是数字。运行spread()后,它变成了一个字符向量。在后面运行gather(),变量名称始终保持为字符向量。

stocks <- tibble(
  year   = c(2015,2015, 2016,2016),
  half  = c(  1,   2,    1,   2),
  return = c(1.88, 0.59, 0.92,0.17)
stocks %>%
  spread(key= "year", value = "return") %>%
  gather(`2015`:`2016`, key = "year", value = "return", convert = TRUE)

2.没有加引号,作为列名,是不能直接查找数字的
3.因为有一组数据作为划分的部分是完全一致的,也就是具有重名无法区分的,可以加一列区分开重复的项即可:

file:////Users/zhaojing/Library/Group%20Containers/UBF8T346G9.Office/TemporaryItems/msohtmlclip/AC10C236-A020-0147-BF2D-F8D8DB299F5B.png
4.调整preg
(preg <- tribble(
  ~pregnant, ~male, ~female,
  "yes",     NA,    10,
  "no",      20,    12 ))
(preg_tidy <- preg %>%
  gather(male, female, key = "sex", value= "count", na.rm = TRUE))

数据拆分:separate()

file:////Users/zhaojing/Library/Group%20Containers/UBF8T346G9.Office/TemporaryItems/msohtmlclip/126EF8B3-C1CC-854D-9ED0-9206E6A16CE2.png
默认情况下,separate()会通过非字母数字字符(即不是数字或字母的字符)进行分割
如果希望使用特定字符来分隔列,则可以将该字符传递给sep参数separate()

table3 %>%
  separate(rate, into= c("cases", "population"),sep = "/",convert = TRUE)
参数 sep = 2 ,可以将数据从一列整数分裂成两列

数据组合:unite()

file:////Users/zhaojing/Library/Group%20Containers/UBF8T346G9.Office/TemporaryItems/msohtmlclip/52B0B8FA-7797-8B42-941F-432E1B3211E2.png
table5 %>%
  unite(new, century, year, sep = "")

12.4练习
1.separate()中extra参数用于指导多余的项目怎么处理,fill则对缺少的项目进行处理
tibble(x = c("a,b,c", "d,e,f,g", "h,i,j")) %>%
  separate(x, c("one", "two", "three"), extra= "drop")  #删除多余的数值g
#> # A tibble: 3 x 3
#>  one   two   three
#>  <chr> <chr> <chr>
#> 1 a    b     c   
#> 2 d    e     f   
#> 3 h    i     j

tibble(x = c("a,b,c", "d,e,f,g", "h,i,j")) %>%
  separate(x, c("one", "two", "three"), extra= "merge") #额外值不会拆分,因此"f,g"在第三列中显示
#> # A tibble: 3 x 3
#>  one   two   three
#>  <chr> <chr> <chr>
#> 1 a    b     c   
#> 2 d    e     f,g  
#> 3 h    i     j

tibble(x = c("a,b,c", "d,e", "f,g,i")) %>%
  separate(x, c("one", "two", "three"), fill = "right") #fill是"right"从右侧开始填充
#> # A tibble: 3 x 3
#>   one  two   three
#>   <chr> <chr> <chr>
#> 1 a     b    c   
#> 2 d     e    <NA>
#> 3 f     g    i

tibble(x = c("a,b,c", "d,e", "f,g,i")) %>%
  separate(x, c("one", "two", "three"), fill ="left") #fill = "left"从左侧开始填充
#> # A tibble: 3 x 3
#>  one   two   three
#>  <chr> <chr> <chr>
#> 1 a    b     c   
#> 2 <NA>  d    e   
#> 3 f    g     I

2.remove = FALSE ,是在创建新的变量时,保留原来的变量
tibble(x = c("a,b,c", "d,e", "f,g,i")) %>%
  separate(x, c("one", "two", "three"), fill = "left", remove = FALSE)
#> # A tibble: 3 x 4
#>   x     one  two   three
#>  <chr> <chr> <chr><chr>
#> 1 a,b,c a    b     c   
#> 2 d,e  NA    d     e   
#> 3 f,g,i f    g     i  

3.
函数separate()通过分隔符将列拆分为多个组(sep = 字符向量)或字符位置(sep = 数字)。
# example withseparators
tibble(x = c("X_1", "X_2", "AA_1", "AA_2")) %>%
  separate(x, c("variable", "into"), sep= "_")
#> #A tibble: 4 x 2
#>   variable into
#>   <chr>    <chr>
#> 1X        1   
#> 2X        2   
#> 3AA       1   
#> 4AA       2
# example withposition
tibble(x = c("X1", "X2", "Y1", "Y2")) %>%
  separate(x, c("variable", "into"), sep= c(1))
#> #A tibble: 4 x 2
#>   variable into
#>   <chr>    <chr>
#> 1X        1   
#> 2X        2   
#> 3Y        1   
#> 4Y        2

函数extract()使用正则表达式指定字符向量中的组,并将该单个字符向量拆分为多个列。这比separate()更灵活,因为它不需要公共分隔符或特定列位置。
# example withseparators
tibble(x = c("X_1", "X_2", "AA_1", "AA_2")) %>%
  extract(x, c("variable", "id"), regex = "([A-Z])_([0-9])")
#> #A tibble: 4 x 2
#>   variable id  
#>   <chr>    <chr>
#> 1X        1   
#> 2X        2   
#> 3A        1   
#> 4A        2
# example withposition
tibble(x = c("X1", "X2", "Y1", "Y2")) %>%
  extract(x, c("variable", "id"), regex = "([A-Z])([0-9])")
#> #A tibble: 4 x 2
#>   variable id  
#>   <chr>    <chr>
#> 1X        1   
#> 2X        2   
#> 3Y        1   
#> 4Y        2
# example thatseparate could not parse
tibble(x = c("X1", "X20", "AA11", "AA2")) %>%
  extract(x, c("variable", "id"), regex = "([A-Z]+)([0-9]+)")
#> #A tibble: 4 x 2
#>   variable id  
#>   <chr>    <chr>
#> 1X        1   
#> 2X        20   
#> 3AA       11   
#> 4AA       2

unite()将许多列转换为一列,并选择要包含在列值之间的分隔符。
tibble(variable = c("X", "X", "Y", "Y"), id = c(1, 2, 1, 2)) %>%
  unite(x, variable, id, sep = "_")
#> #A tibble: 4 x 1
#>   x   
#>   <chr>
#> 1X_1  
#> 2X_2  
#> 3Y_1  
#> 4Y_2

总结:extract()&separate()只能选择一列进行操作,但是如何将该单个列拆分为不同的列有很多选择。
而对于unite()要包含哪些列,有很多选择,但只能将选择的内容组合到单个向量中。

缺失值的处理

更改数据集的表示形式会带来缺失值。并可能会以两种可能的方式之一呈现:
明确地,即标记为NA。
隐含地,即简单地不存在于数据中。
举例:
stocks <- tibble(
  year   = c(2015,2015, 2015,2015, 2016,2016, 2016),
  qtr    = c(  1,   2,   3,   4,   2,   3,   4),
  return = c(1.88, 0.59, 0.35,   NA, 0.92, 0.17, 2.66)
)

这里就明显的存在缺失值:
显然缺少2015年第四季度的回报,因为其值应包含的单元格NA。
隐含地缺少2016年第一季度的回报,因为它根本没有出现在数据集中。

可以通过改变数据表现形式使隐含的缺失值显示出来:
stocks %>%
  spread(year, return)
#> #A tibble: 4 x 3
#>     qtr `2015` `2016`
#>   <dbl> <dbl>  <dbl>
#>1     1  1.88  NA   
#>2     2  0.59   0.92
#>3     3  0.35   0.17
#>4     4 NA      2.66


当某些明确的缺失值不是重要信息时,可以在gather()设置na.rm = TRUE,将显性缺失值转为隐含式的:

stocks %>%
  spread(year, return) %>%
  gather(year, return, `2015`:`2016`, na.rm = TRUE)

在整洁数据中显示缺失值的另一个重要工具是complete()
treatment <- tribble(
  ~ person,           ~ treatment,~response,
  "Derrick Whitmore", 1,           7,
  NA,                 2,           10,
  NA,                 3,           9,
  "Katherine Burke",  1,           4
)
treatment %>%
  fill(person) #用fill填写缺失值,会将缺失值替换为最近的非缺失值(有时称为最后一次观察结果)
#> # A tibble: 4 x 3
#>  person           treatmentresponse
#>  <chr>               <dbl>    <dbl>
#> 1 Derrick Whitmore         1        7
#> 2 Derrick Whitmore         2      10
#> 3 Derrick Whitmore         3        9
#> 4 Katherine Burke          1        4


12.5练习
1.在spread(),fill参数显式设置值以替换NA。在complete(),fill参数还设置一个值来替换NA,但它被命名为list,允许不同变量的不同值。此外,两种情况都会替换隐式成为显式缺失值。
2.fill,它确定NA是否被替换为前一个的非缺失值("down")或后一个的非缺失值("up")

案例

who %>%
  gather(key, value, new_sp_m014:newrel_f65,na.rm = TRUE) %>%       #更改结构,去掉NA值
  mutate(key =stringr::str_replace(key, "newrel", "new_rel")) %>% #统一变量名
  separate(key, c("new", "var", "sexage")) %>%
  select(-new, -iso2, -iso3) %>%
  separate(sexage, c("sex", "age"), sep = 1)

练习12.6
1.who1 %>%filter(cases == 0) %>%nrow()
#> [1] 11080
数据中有零,这意味着NA可能明确表示没有案例。?????
gather(who, new_sp_m014:newrel_f65, key = "key", value = "cases") %>%
  group_by(country, year)  %>%
  mutate(missing= is.na(cases)) %>%
  select(country, year, missing) %>%
  distinct() %>%
  group_by(country, year) %>%
  filter(n() > 1)
2.会报错,因为前后的变量名是不同的
3.检测有没有不同代表方式,结果是没有。所以可以说这三列信息是重复的
select(who3, country, iso2, iso3) %>%
  distinct() %>%
  group_by(country) %>%
  filter(n() > 1)
#> #A tibble: 0 x 3
#> #Groups:   country [0]
#> #... with 3 variables: country <chr>, iso2 <chr>, iso3 <chr>
4.
who5 %>%
  group_by(country, year, sex) %>%
  filter(year >1995) %>%
  summarise(cases= sum(cases)) %>%
  unite(country_sex, country, sex, remove = FALSE) %>%
  ggplot(aes(x = year, y= cases, group = country_sex, colour = sex)) +
  geom_line()
file:////Users/zhaojing/Library/Group%20Containers/UBF8T346G9.Office/TemporaryItems/msohtmlclip/15AD8106-360D-3142-968B-627B969ABD92.png







上一篇:癌症组织与癌旁组织的T细胞受体差异过大正常吗
下一篇:StepReg:我的第一个R语言程序包
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|生信技能树    

GMT+8, 2018-12-12 03:06 , Processed in 0.033585 second(s), 26 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.