美文网首页生信Python
[Python/R语言] 用R和python解决数据分析120题

[Python/R语言] 用R和python解决数据分析120题

作者: 半为花间酒 | 来源:发表于2020-04-16 12:24 被阅读0次

转载请注明:陈熹 chenx6542@foxmail.com (简书号:半为花间酒)
若公众号内转载请联系公众号:早起Python
题源:
早起python 《Pandas进阶修炼120题》

数据:
https://pan.baidu.com/s/1UoN4qcj4Fzbk1EWBagd-8g
提取码:b7h7

数据分析120题系列:

为什么出这个专题:

R语言和pandas都是数据处理的重要工具
而二者的高下争论时有存在
我相信对于数据而言没有绝对的孰优孰劣
需要做的应该是在必要时权衡最合适的办法

感谢 公众号早起python 提供数据分析120题
这些题目是一个契机
帮助我比较了两种语言处理不同问题的共性
当然也发现了各自的灵活和缺陷

它们覆盖多数数据分析初期可能遇到的问题
无论是对R语言还是对python技能的提升
相信都有很大帮助

(陈熹 2020年4月)

  • python解法
import pandas as pd
import numpy as np

df = pd.read_excel(r'C:\Users\chenx\Documents\Data Analysis\Pandas51-80.xls')
  • R解法
    可以用openxlsx包或java环境的xlsx包读,详见21题
    也可以用非常智能的rio包
    还能简化直接用readr包读csv
rio::import('C:/Users/chenx/Documents/Data Analysis/Pandas51-80.xls')

# 也可以转存csv后再读
library(readr)
df <- read_csv('C:/Users/chenx/Documents/Data Analysis/Pandas51-80.csv')

# rio包支持文件转化,但数据中的中文会出现乱码,推荐英文可以用以下方法
rio::convert('test.xlsx','test.csv')

  • python解法
df.head(3)
  • R解法
head(df,3)
pandas / R
  • python解法
df.isnull().sum()
  • R解法
colSums(is.na(df))
pandas / R
  • python解法
df[df['日期'].isnull()]
  • R解法
df[is.na(df$日期),]
pandas / R
  • python解法
for i in df.columns:
    if df[i].count() != len(df):
        row = df[i][df[i].isnull().values].index.tolist()
        print('列名:"{}", 第{}行位置有缺失值'.format(i,row))
  • R解法
library(glue)

for (i in names(df)){
  if(sum(is.na(df[,'日期'])) != 0){
    res1 <- which(is.na(df[,i]))
    res2 <- paste(res1,collapse = ',')
    print(glue('列名:"{i}", 第[{res2}]行有缺失值'))
  }
}

(注:pandas的行数是从0开始计算的)

pandas / R
  • python解法
df.dropna(axis=0, how='any', inplace=True)
  • R解法
df <- na.omit(df)
pandas / R
  • python解法
# Jupyter运行matplotlib
%matplotlib inline

df['收盘价(元)'].plot()
# 等价于
import matplotlib.pyplot as plt
plt.plot(df['收盘价(元)'])
  • R解法
library(ggplot2)

df %>% 
  ggplot(aes(日期,`收盘价(元)`)) +
  geom_line()
pandas / R
  • python解法
plt.rcParams['font.sans-serif'] = ['SimHei'] # 解决中文乱码
plt.rcParams['axes.unicode_minus'] = False # 解决符号问题

df[['收盘价(元)','开盘价(元)']].plot()
  • R解法
df %>% 
  ggplot() +
  geom_line(aes(日期,`收盘价(元)`), size=1.2, color='steelblue') +
  geom_line(aes(日期,`开盘价(元)`), size=1.2, color='orange') +
  ylab(c('价格(元)'))
# 这种画出来没有图例,当然可以手动添加,但为了映射方便可以用另一种方法

library(tidyr)

df %>% 
  select(日期,`开盘价(元)`,`收盘价(元)`) %>% 
  pivot_longer(c(`开盘价(元)`,`收盘价(元)`),
               names_to='type',values_to='price') %>% 
  ggplot(aes(日期,price,color=type)) +
  geom_line(size=1.2) +
  scale_color_manual(values=c('steelblue','orange')) +
  theme_bw() + 
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(), 
    legend.title = element_blank(),
    legend.position = c(0.86, 0.9)
  )
pandas / R
  • python解法
plt.hist(df['涨跌幅(%)'])
# 等价于
df['涨跌幅(%)'].hist()
  • R解法
df %>% 
  ggplot(aes(`涨跌幅(%)`)) +
  geom_histogram()
# 可以指定bins
pandas / R
  • python解法
df['涨跌幅(%)'].hist(bins = 30)
  • R解法
df %>% 
  ggplot(aes(`涨跌幅(%)`)) +
  geom_histogram(bins=30)

这是很有意义的一次结果
可以发现matplotlib和ggplot2做直方图采取的划分策略是不同的

pandas / R
  • python解法
temp = pd.DataFrame(columns = df.columns.to_list())
  • R解法
temp <- as_tibble(names(df))

  • python解法
for index,row in df.iterrows():
    if type(row[13]) != float:
        temp = temp.append(df.loc[index])
  • R解法
    换手率这一列属性为chr,需要先强转数值型
    如果转换失败会变成NA,判断即可
df[is.na(as.numeric(df$`换手率(%)`)),]
pandas / R
  • python解法
df[df['换手率(%)'] == '--']
  • R解法
df %>% 
  filter(`换手率(%)` == '--')

结果同上一题


  • python解法
df = df.reset_index(drop=True)
  • R解法
rownames(df) <- NULL

# 如果是tibble则索引始终是按顺序

  • python解法
lst = []
for index,row in df.iterrows():
    if type(row[13]) != float:
        lst.append(index)
df.drop(labels=lst,inplace=True)
  • R解法
df[!is.na(as.numeric(df$`换手率(%)`)),]
# 或者根据前几题的经验,非数字就是'--'
df <- df %>% 
  filter(`换手率(%)` != '--')
pandas / R
  • python解法
df['换手率(%)'].plot(kind='kde',xlim=(0,0.6))
  • R解法
df$`换手率(%)` <-  as.double(df$`换手率(%)`)
ggplot(df) +
  geom_density(aes(`换手率(%)`))
pandas / R
  • python解法
df['收盘价(元)'].diff()
  • R解法
df %>% 
  summarise(delta = `收盘价(元)` - lag(`收盘价(元)`))
pandas / R
  • python解法
data['收盘价(元)'].pct_change()
  • R解法
df %>% 
  summarise(pct_change = (`收盘价(元)` - lag(`收盘价(元)`))/lag(`收盘价(元)`))
pandas / R
  • python解法
df.set_index('日期')
  • R解法
df %>% 
  column_to_rownames(var='日期')
pandas / R
  • python解法
df['收盘价(元)'].rolling(5).mean()
  • R解法
    利用RcppRoll包开窗
library(RcppRoll)
df %>% 
  transmute(avg_5 = roll_mean(`收盘价(元)`,n = 5,align="right",fill = NA))
pandas / R
  • python解法
df['收盘价(元)'].rolling(5).sum()
  • R解法
df %>% 
  transmute(sum_5 = roll_sum(`收盘价(元)`,n = 5,align="right",fill = NA))
pandas / R
  • python解法
df['收盘价(元)'].plot()
df['收盘价(元)'].rolling(5).mean().plot()
df['收盘价(元)'].rolling(20).mean().plot()
  • R解法
df %>% 
  mutate(avg_5 = roll_mean(`收盘价(元)`,n = 5,align="right",fill = NA),
         avg_20 = roll_mean(`收盘价(元)`,n = 20,align="right",fill = NA)) %>% 
  ggplot() +
  geom_line(aes(日期,`收盘价(元)`),color = 'steelblue',size = 1.2) +
  geom_line(aes(日期,avg_5),color = 'orange',size = 1.2) +
  geom_line(aes(日期,avg_20),color = 'green',size = 1.2)
pandas / R
  • python解法
    进行重抽样前需要保证索引是日期(时间)格式
df = df.set_index('日期')
df['收盘价(元)'].resample('W').max()
  • R解法
    我不是专业做量化交易的
    时间序列的处理不是很熟悉
    用R和python的结果存在出入待后续解决
library(plyr)

res <- dlply(df,.(cut(日期,"1 week")),"[") 
res_max <- sapply(res,function(n)max(n$`收盘价(元)`),simplify=TRUE)
as.data.frame(res_max)
pandas / R
  • python解法
df['收盘价(元)'].plot()
df['收盘价(元)'].resample('7D').max().plot()
  • R解法
res %>% 
  rownames_to_column('date') 
res$date <- as.Date(res$date)

ggplot(df) +
  geom_line(aes(日期,`收盘价(元)`),color = 'steelblue',size = 1.2) + 
  geom_line(data = res, aes(date,res_max),
            color = 'orange',size = 1.2)
pandas / R
  • python解法
df.shift(5)
  • R解法
lag(df,5)
pandas / R
  • python解法
df.shift(-5)
  • R解法
lead(df,5)

结果类似上一题,故不展示


  • python解法
df['开盘价(元)'].expanding(min_periods=1).mean()
  • R解法
    R中没有expanding完全一致的函数
    考虑到expanding实际功能就是累积均值
    可以用cummean
    但cummean的功能和我预想的不同
    可能是包之间相互干扰
    最后采用cumsum/1:n的形式完成本题
res <- df %>% 
  transmute(cummean = cumsum(`开盘价(元)`)/1:dim(df)[1])
pandas / R
  • python解法
df['expanding Open mean']=df['开盘价(元)'].expanding(min_periods=1).mean()
df[['开盘价(元)', 'expanding Open mean']].plot(figsize=(16, 6))
  • R解法
library(tidyr)
df %>% 
  cbind(res) %>% 
  dplyr::rename(Opening_Price = `开盘价(元)`,
         Expanding_Open_Mean = cummean) %>% 
  select(日期,Opening_Price,Expanding_Open_Mean) %>% 
  pivot_longer(c(Opening_Price,Expanding_Open_Mean),
               names_to = 'type',
               values_to ='price') %>% 
  ggplot(aes(日期,price,color = type)) +
  geom_line(size=1.2) +
  scale_color_manual(values=c('orange','steelblue')) +
  theme_bw() + 
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(), 
    legend.title = element_blank(),
    legend.position = c(0.9, 0.9)
  )
pandas / R

布林线指标,即BOLL指标,其英文全称是“Bollinger Bands”,布林线(BOLL)由约翰·布林先生创造,其利用统计原理,求出股价的标准差及其信赖区间

  • python解法
df['former 30 days rolling Close mean']=df['收盘价(元)'].rolling(20).mean()
df['upper bound']=df['former 30 days rolling Close mean']+2*df['收盘价(元)'].rolling(20).std()
df['lower bound']=df['former 30 days rolling Close mean']-2*df['收盘价(元)'].rolling(20).std()
  • R解法
df <- df %>% 
  mutate(avg_20 = roll_mean(`收盘价(元)`,n = 20,align="right",fill = NA),
         upper_bound = avg_20 + 2 * roll_sd(`收盘价(元)`,n = 20,align="right",fill = NA),
         lower_bound = avg_20 - 2 * roll_sd(`收盘价(元)`,n = 20,align="right",fill = NA))

算的结果对不对最后一题见分晓


  • python解法
df[['收盘价(元)', 'former 30 days rolling Close mean','upper bound','lower bound' ]].plot(figsize=(16, 6))
  • R解法
df %>% 
  dplyr::rename(former_30_days_rolling_Close_mean = avg_20,
                Closing_Price = `收盘价(元)`) %>%
  select(日期,Closing_Price,
           former_30_days_rolling_Close_mean,upper_bound,lower_bound) %>% 
  pivot_longer(c(Closing_Price,former_30_days_rolling_Close_mean,upper_bound,lower_bound),
               names_to = 'type',
               values_to ='price') %>% 
  ggplot(aes(日期,price,color = type)) +
  geom_line(size=1.2) +
  scale_color_manual(values=c('steelblue','orange','red','green')) +
  theme_bw() + 
  theme(
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(), 
    legend.title = element_blank(),
    legend.position = c(0.6, 0.2)
  )
pandas / R

相关文章

网友评论

    本文标题:[Python/R语言] 用R和python解决数据分析120题

    本文链接:https://www.haomeiwen.com/subject/oclcvhtx.html