はじめに

deepblueインターン生の中山です。
PythonとRを交互に書く時に毎回迷うので、備忘録のblogとして残そうと思います。
今回は基本的なデータフレームの簡単な操作についてまとめようと思います。

連載

利用したデータ

今回使用したデータは、MineThatData E-Mail Analytics And Data Mining Challenge datasetです。
効果検証入門内で解析されているデータセットです。
データの詳細は今回は重要ではないので割愛しますが、興味のある方はWEBサイトからデータを確認してみてください。

簡単な操作

コードの具体的な説明をする前に、PythonとRで異なる表記やショートカットの差異について記述致します。
ここでは、Windowsの場合を想定しております。

Python (Jupyter Notebook)

  • 代入:=
  • コメントアウト:ctrl + /
  • やり直し:ctrl + y

R (Rstudio)

  • 代入:<-
  • コメントアウト:shift + ctrl + c
  • やり直し:shift + ctrl + z
  • パイプ演算子(%>%):shift + ctrl + m

データ読み込み

csvデータを読み込んで、データフレームを確認するコード。

Python

  • pd.read_csv()
import pandas as pd
PATH = "http://www.minethatdata.com/Kevin_Hillstrom_MineThatData_E-MailAnalytics_DataMiningChallenge_2008.03.20.csv"
df = pd.read_csv(PATH)
df.head()

#   recency history_segment history mens womens  zip_code newbie channel       segment visit conversion spend
# 0      10  2) $100 - $200  142.44    1      0 Surburban      0   Phone Womens E-Mail     0          0     0
# 1       6  3) $200 - $350  329.08    1      1     Rural      1     Web     No E-Mail     0          0     0
# 2       7  2) $100 - $200  180.65    0      1 Surburban      1     Web Womens E-Mail     0          0     0
# 3       9  5) $500 - $750  675.83    1      0     Rural      1     Web   Mens E-Mail     0          0     0
# 4       2    1) $0 - $100   45.34    1      0     Urban      0     Web Womens E-Mail     0          0     0

R

  • read.csv()
PATH <- "http://www.minethatdata.com/Kevin_Hillstrom_MineThatData_E-MailAnalytics_DataMiningChallenge_2008.03.20.csv"
df <- read.csv(PATH)
head(df)

#   recency history_segment history mens womens  zip_code newbie channel       segment visit conversion spend
# 1      10  2) $100 - $200  142.44    1      0 Surburban      0   Phone Womens E-Mail     0          0     0
# 2       6  3) $200 - $350  329.08    1      1     Rural      1     Web     No E-Mail     0          0     0
# 3       7  2) $100 - $200  180.65    0      1 Surburban      1     Web Womens E-Mail     0          0     0
# 4       9  5) $500 - $750  675.83    1      0     Rural      1     Web   Mens E-Mail     0          0     0
# 5       2    1) $0 - $100   45.34    1      0     Urban      0     Web Womens E-Mail     0          0     0
# 6       6  2) $100 - $200  134.83    0      1 Surburban      0   Phone Womens E-Mail     1          0     0

行数・列数の確認

データの行数、列数を確認するコード。

Python

  • 行数 x 列数:shape
  • 行数:shape[0]
  • 列数:shape[1]
df.shape

# (64000, 12)

df.shape[0]

# 64000

df.shape[1]

# 12

R

  • 行数 x 列数:dim()
  • 行数:nrow()
  • 列数:ncol()
df %>% dim()
# dim(df)# こちらでも可

# [1] 64000    12

df %>% nrow()
# nrow(df)# こちらでも可

# [1] 64000

df %>% ncol()
# ncol(df)# こちらでも可

# [1] 12

型の確認

データ各列の型を確認するコード。
Rだとstrで表すため、文字列と間違えないよう注意が必要です。

Python

  • dtypes
df.dtypes

# recency              int64
# history_segment     object
# history            float64
# mens                 int64
# womens               int64
# zip_code            object
# newbie               int64
# channel             object
# segment             object
# visit                int64
# conversion           int64
# spend              float64
# dtype: object

R

  • str()
df %>% str()
# str(df)# こちらでも可

# 'data.frame': 64000 obs. of  12 variables:
# $ recency        : int  10 6 7 9 2 6 9 9 9 10 ...
# $ history_segment: Factor w/ 7 levels "1) $0 - $100",..: 2 3 2 5 1 2 3 1 5 1 ...
# $ history        : num  142.4 329.1 180.7 675.8 45.3 ...
# $ mens           : int  1 1 0 1 1 0 1 0 1 0 ...
# $ womens         : int  0 1 1 0 0 1 0 1 1 1 ...
# $ zip_code       : Factor w/ 3 levels "Rural","Surburban",..: 2 1 2 1 3 2 2 3 1 3 ...
# $ newbie         : int  0 1 1 1 0 0 1 0 1 1 ...
# $ channel        : Factor w/ 3 levels "Multichannel",..: 2 3 3 3 3 2 2 2 2 3 ...
# $ segment        : Factor w/ 3 levels "Mens E-Mail",..: 3 2 3 1 3 3 3 3 1 3 ...
# $ visit          : int  0 0 0 0 0 1 0 0 0 0 ...
# $ conversion     : int  0 0 0 0 0 0 0 0 0 0 ...
# $ spend          : num  0 0 0 0 0 0 0 0 0 0 ...

要約統計量

データフレーム各列の要約統計量などを取得するコード。
Rはsummaryを使うことで、質的変数(主にfactor型)にも適用可能です。

Python

  • describe()
df.describe()

#             recency       history          mens        womens        newbie         visit    conversion         spend
# count  64000.000000  64000.000000  64000.000000  64000.000000  64000.000000  64000.000000  64000.000000  64000.000000
# mean       5.763734    242.085656      0.551031      0.549719      0.502250      0.146781      0.009031      1.050908
# std        3.507592    256.158608      0.497393      0.497526      0.499999      0.353890      0.094604     15.036448
# min        1.000000     29.990000      0.000000      0.000000      0.000000      0.000000      0.000000      0.000000
# 25%        2.000000     64.660000      0.000000      0.000000      0.000000      0.000000      0.000000      0.000000
# 50%        6.000000    158.110000      1.000000      1.000000      1.000000      0.000000      0.000000      0.000000
# 75%        9.000000    325.657500      1.000000      1.000000      1.000000      0.000000      0.000000      0.000000
# max       12.000000   3345.930000      1.000000      1.000000      1.000000      1.000000      1.000000    499.000000

R

  • summary()
df %>% summary()
# summary(df)# こちらでも可

#    recency               history_segment     history             mens           womens            zip_code
# Min.   : 1.000   1) $0 - $100    :22970   Min.   :  29.99   Min.   :0.000   Min.   :0.0000   Rural    : 9563
# 1st Qu.: 2.000   2) $100 - $200  :14254   1st Qu.:  64.66   1st Qu.:0.000   1st Qu.:0.0000   Surburban:28776
# Median : 6.000   3) $200 - $350  :12289   Median : 158.11   Median :1.000   Median :1.0000   Urban    :25661
# Mean   : 5.764   4) $350 - $500  : 6409   Mean   : 242.09   Mean   :0.551   Mean   :0.5497
# 3rd Qu.: 9.000   5) $500 - $750  : 4911   3rd Qu.: 325.66   3rd Qu.:1.000   3rd Qu.:1.0000
# Max.   :12.000   6) $750 - $1,000: 1859   Max.   :3345.93   Max.   :1.000   Max.   :1.0000
#                  7) $1,000 +     : 1308
#
#     newbie               channel               segment          visit          conversion
# Min.   :0.0000   Multichannel: 7762   Mens E-Mail  :21307   Min.   :0.0000   Min.   :0.000000
# 1st Qu.:0.0000   Phone       :28021   No E-Mail    :21306   1st Qu.:0.0000   1st Qu.:0.000000
# Median :1.0000   Web         :28217   Womens E-Mail:21387   Median :0.0000   Median :0.000000
# Mean   :0.5022                                              Mean   :0.1468   Mean   :0.009031
# 3rd Qu.:1.0000                                              3rd Qu.:0.0000   3rd Qu.:0.000000
# Max.   :1.0000                                              Max.   :1.0000   Max.   :1.000000
#
#     spend
# Min.   :  0.000
# 1st Qu.:  0.000
# Median :  0.000
# Mean   :  1.051
# 3rd Qu.:  0.000
# Max.   :499.000

番号指定

PythonとRは、数字で指定を行う時に違いがあるため、その差異について示します。
また、同じデータを表示するコードをPythonとRで示します。

Python

  • 最初の番号:0番
  • [a:b]a:含む
  • [a:b]b:含まない
df.iloc[0:5,1:4]

#   history_segment  history  mens
# 0  2) $100 - $200   142.44     1
# 1  3) $200 - $350   329.08     1
# 2  2) $100 - $200   180.65     0
# 3  5) $500 - $750   675.83     1
# 4    1) $0 - $100    45.34     1

R

  • 最初の番号:1番
  • [a:b]a:含む
  • [a:b]b:含む
df[1:5,2:4]

#   history_segment history mens
# 1  2) $100 - $200  142.44    1
# 2  3) $200 - $350  329.08    1
# 3  2) $100 - $200  180.65    0
# 4  5) $500 - $750  675.83    1
# 5    1) $0 - $100   45.34    1

列の選択

読み込んだデータフレームにおいて、特定の列を選択するコード。
また、Rではtidyverseを用いない場合のコードも載せています。

Python

  • [["hoge", "fuga"]]
  • loc[:,["hoge", "fuga"]]
df_new = df[["recency", "history", "zip_code"]]
df_new = df.loc[:, ["recency", "history", "zip_code"]]

# df_new.head()
#    recency  history   zip_code
# 0       10   142.44  Surburban
# 1        6   329.08      Rural
# 2        7   180.65  Surburban
# 3        9   675.83      Rural
# 4        2    45.34      Urban

R

  • select(hoge, fuga)
# tidyverseの場合
df_new <- df %>%
  select(recency, history, zip_code)

# tidyverseを利用しない場合
# df_new <- df[c("recency", "history", "zip_code")]

# df_new %>% head()
#   recency history  zip_code
# 1      10  142.44 Surburban
# 2       6  329.08     Rural
# 3       7  180.65 Surburban
# 4       9  675.83     Rural
# 5       2   45.34     Urban
# 6       6  134.83 Surburban

行の抽出

データフレームから、条件に合致するデータを抽出するコード。
今回はhistory > 3000channel == "Phone"の2つの条件を設定しております。

Python

  • [(hoge > a) & (fuga == b)]
df_new = df[(df.history > 3000) & (df.channel == "Phone")]

# df_new
#        recency history_segment  history  mens  womens   zip_code  newbie  channel    segment  visit  conversion  spend
# 4579         2     7) $1,000 +  3345.93     1       1  Surburban       1    Phone  No E-Mail      0           0    0.0
# 43060        1     7) $1,000 +  3003.48     1       1      Urban       1    Phone  No E-Mail      0           0    0.0

R

  • filter(hoge > a, fuga == b)
# tidyverseの場合
df_new <- df %>%
  filter(history > 3000,
         channel == "Phone")

# tidyverseを利用しない場合
# df_new <- df[df$history > 3000 & df$channel == "Phone",]

# df_new
#   recency history_segment history mens womens  zip_code newbie channel   segment visit conversion spend
# 1       2     7) $1,000 + 3345.93    1      1 Surburban      1   Phone No E-Mail     0          0     0
# 2       1     7) $1,000 + 3003.48    1      1     Urban      1   Phone No E-Mail     0          0     0

データ代入

条件に合致するとき、特定の列に値を代入するコード。
ここでは、spendの列に1000を代入しています。
history > 3000の条件はデータを確認しやすくするためで、特に意味はないです。

Python

  • assign(hoge = a)
df_new = df[df.history > 3000].assign(spend = 1000)

# df_new
#        recency history_segment  history  mens  womens   zip_code  newbie       channel        segment  visit  conversion  spend
# 4579         2     7) $1,000 +  3345.93     1       1  Surburban       1         Phone      No E-Mail      0           0   1000
# 38680        1     7) $1,000 +  3215.97     1       1      Urban       1  Multichannel    Mens E-Mail      1           0   1000
# 43060        1     7) $1,000 +  3003.48     1       1      Urban       1         Phone      No E-Mail      0           0   1000
# 52860        1     7) $1,000 +  3040.20     0       1      Urban       1           Web  Womens E-Mail      0           0   1000

R

  • mutate(hoge = a)
# tidyverseの場合
df_new <- df %>%
  filter(history > 3000) %>%
  mutate(spend = 1000)

# tidyverseを利用しない場合
# df[df$history > 3000, "spend"] <- 1000

# df_new
#   recency history_segment history mens womens  zip_code newbie      channel       segment visit conversion spend
# 1       2     7) $1,000 + 3345.93    1      1 Surburban      1        Phone     No E-Mail     0          0  1000
# 2       1     7) $1,000 + 3215.97    1      1     Urban      1 Multichannel   Mens E-Mail     1          0  1000
# 3       1     7) $1,000 + 3003.48    1      1     Urban      1        Phone     No E-Mail     0          0  1000
# 4       1     7) $1,000 + 3040.20    0      1     Urban      1          Web Womens E-Mail     0          0  1000

連載