R函数踩坑

variaty of R function

1 分析场景与R包

1.1 统计制表 vs janitor::tabyl

tabyls: a tidy, fully-featured approach to counting things. see link

  • 优点

    • 方便统计频次和频率

    • 方便添加行合计

    • 方便调整数据格式(百分数等)

    • 可以结合knitr::kable()输出

  • 不足

    • janitor::tabyl()仅适合处理原始数据,并且是data.framevector

1.1.1 注意函数使用次序

特别需要注意系列janitor::adorn_xx()函数的使用先后顺序关系。概括起来需要小心的是:

  • 先计算汇总,再设置格式。其核心要点在于,数据列格式的变换,会导致数据列类型(type)的改变,比如numeric类型会变为character类型。例如,需要先adorn_total("rows")进行行汇总,再adorn_pct_formatting()把比率转换为百分数。

  • 没有被汇总的adorn_total(),也不会被进一步调整格式adorn_pct_formatting()。这意味着手动计算的占比列(小数如0.32),不能够使用adorn_pct_formatting()调整为百分数(如32%)。

  • 添加汇总计算adorn_total(),结果将不再保持为标准数据表(tidy data table)。因此需要额外处理不适合汇总的列或行。例如累积百分比和累积次数,就不应该有汇总(Total)值。

1.1.2 指定列进行汇总或调整格式

  • 首先,指定列进行汇总或调整格式需要满足前述函数使用的先后次序关系。

  • 其次,指定列进行汇总或调整格式需要完整使用janitor::adorn_xx()函数的所有参数设置。这一点非常不人性。

  • 最后,指定列进行汇总或调整格式需要使用dplyr包的select语法,如all_of(contains(“p”))`。

require(DT)
require(janitor)
char <-c("非常不满意","不满意","一般","满意","非常满意")
reps <- c(24L, 108L,93L, 45L,30L) 

sat_list <- rep(char, reps)

sat <- data.frame(groups=LETTERS[1:5],
                  satisfication = sat_list,
                  row.names=NULL) %>%
  mutate(satisfication = factor(satisfication, levels = char))

cum_calc <- sat %>%
  janitor::tabyl(satisfication) %>%
  mutate(min_cum_n = cumsum(n),
         min_cum_p = cumsum(percent), #<<
         max_cum_n =rev( cumsum(rev(n))), #<<
         max_cum_p =rev( cumsum(rev(percent)))) 
  
cum_format<-  cum_calc %>%
  mutate(min_cum_p = scales::percent(min_cum_p,accuracy = 0.1), #<<
         max_cum_p = scales::percent(max_cum_p,accuracy = 0.1)) %>%
  janitor::adorn_totals(.,where = "row",fill = "-",na.rm = TRUE, #<<
                        name = "Total", all_of(c("n","percent"))) %>%
  janitor::adorn_pct_formatting(.,digits = 1, #<<
                                rounding ="half to even",
                                affix_sign = TRUE,
                                all_of(c("percent"))) #<<

2 分析场景与R函数

2.1 数据类型读取

  • 读取spss文件。为了避免出现编码错误(中文等多字节问题),建议使用foreign::read.spss()函数,而不宜使用haven::read_sav()函数
df_computer<- haven::read_sav("../data/case-3.6-computer-sales.sav",encoding = "UTF-8", .name_repair = "unique")

knitr::kable(df_computer)
df_computer<- foreign::read.spss("../data/case-3.6-computer-sales.sav", to.data.frame=TRUE)
knitr::kable(df_computer)

2.2 生成重复数据rep()

分析场景:生成指定的重复数据,要求指定被重复的vector("char vec"),以及指定各自重复的次数vector("times vec")

  • 踩坑函数1:直接rep()
require(magrittr)
brand<- c("果汁","矿泉水","绿茶","其他","碳酸饮料")
reps <- c(6L, 10L,11L, 8L,15L)

rep(brand, reps)
 [1] "果汁"     "果汁"     "果汁"     "果汁"     "果汁"     "果汁"    
 [7] "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"  
[13] "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"   "绿茶"     "绿茶"    
[19] "绿茶"     "绿茶"     "绿茶"     "绿茶"     "绿茶"     "绿茶"    
[25] "绿茶"     "绿茶"     "绿茶"     "其他"     "其他"     "其他"    
[31] "其他"     "其他"     "其他"     "其他"     "其他"     "碳酸饮料"
[37] "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料"
[43] "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料"
[49] "碳酸饮料" "碳酸饮料"
  • 踩坑函数2mapply() + rep()。这个要复杂一点。
drink <- mapply(FUN = rep, x=brand, times = reps) %>%
  unlist()

names(drink) <-NULL

drink
 [1] "果汁"     "果汁"     "果汁"     "果汁"     "果汁"     "果汁"    
 [7] "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"  
[13] "矿泉水"   "矿泉水"   "矿泉水"   "矿泉水"   "绿茶"     "绿茶"    
[19] "绿茶"     "绿茶"     "绿茶"     "绿茶"     "绿茶"     "绿茶"    
[25] "绿茶"     "绿茶"     "绿茶"     "其他"     "其他"     "其他"    
[31] "其他"     "其他"     "其他"     "其他"     "其他"     "碳酸饮料"
[37] "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料"
[43] "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料" "碳酸饮料"
[49] "碳酸饮料" "碳酸饮料"

2.3 探查样本数据集是否缺失

  • 问题:lm(formula = lm.mod, data = lm.dt)回归提示warning。表明数据集lm.dt中存在缺失值。
12 observation deleted due to missingness

Related