EDA Salon 第6回 - 日本の統計データ(e-Stat)のデータラングリング大会
EDA Salon 第6回 - 日本の統計データ(e-Stat)のデータラングリング大会 年齢・男女別人口推移データ(難易度:普通)
相違
Pandasで解いてみたのですが統計の合計が合わない
小数点以下が省略されているため合計が合わないようです
あ,よく見たら,生命表なんですね。小数点以下を省略してあるので合わないのでは?
— Haruhiko Okumura (@h_okumura) 2020年2月2日
全部
抽出
import pandas as pd df = pd.read_excel("https://www.e-stat.go.jp/stat-search/file-download?statInfId=000013168604&fileKind=0", header=None, skiprows=6) df.head(20) # 英語の行削除 df.drop(df.index[4], inplace=True) # 英語の列削除 df.drop(df.columns[1], axis=1, inplace=True) #df.replace("[a-zA-Z]", "", regex=True, inplace=True) #df.mask(df == "", inplace=True) # 年の「1)」を除去 df.iloc[0,:].replace("1\)", "", regex=True, inplace=True) # 空白文字を除去 df.replace(r"\s", "", regex=True, inplace=True) # 年の平成を除去 df.iloc[0,:].replace(r"平成(\d{2})年", "", regex=True, inplace=True) # 年の欠損値を前の値で補完 df.iloc[0,:].fillna(method="ffill", inplace=True) # 年齢の数字以外を除去 df.iloc[:,0].replace(r"歳(以上)?$", "", regex=True, inplace=True) # タイトル補完 df.iloc[0, 0] = "年" df.iloc[2, 0] = "性別" # データ以外を行・列除去 df1 = df.loc[df.notnull().sum(axis=1) > 2, df.notnull().sum() > 2].copy() # 欠損値を0で補間 df1.fillna(0, inplace=True) df1 df1.T.to_csv("data.csv", encoding="utf_8_sig", index=False, header=False)
再集計
df2 = pd.read_csv("data.csv", index_col=[0,1], header=0) df2.head(10) df2a = df2["総数"] - df2.loc[:, "0":"100"].sum(axis=1) df2b = df2a.reset_index() df2b.rename(columns={0:"差"}, inplace=True) df2b.pivot_table(index="年", columns="性別", values="差") df3 = pd.read_csv("data.csv", index_col=None, header=0) df3.head(10) df3.drop("総数", axis=1, inplace=True) df3.head() df4 = df3.melt(id_vars=["年", "性別"], var_name="年齢", value_name="人数") df4.head(10) pv4 = df4.pivot_table(index="年", columns="性別", values="人数", aggfunc="sum") pv4["集計"] = pv4["男"] + pv4["女"] pv4["差"] = pv4["男女計"] - pv4["集計"] pv4 df4["年齢"] = df4["年齢"].astype(int) pv5 = df4.pivot_table(index=["年", "年齢"], columns="性別", values="人数", aggfunc="sum") pv5["男女計"] = pv5["男"] + pv5["女"] pv5.head(10) pv = pv5.stack().reset_index().rename(columns={0:"人数"}) pv1 = pv.pivot_table(index=["年", "性別"], columns="年齢", values="人数") pv1.index new_idx = pd.MultiIndex.from_product([[2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015], ["男女計", "男", "女"]], names=pv1.index.names) pv2 = pv1.reindex(new_idx) new_idx = pd.MultiIndex.from_product([range(2000,2016), ["男女計", "男", "女"]], names=pv1.index.names) pv2 = pv1.reindex(new_idx) pv2["総数"] = pv2.sum(axis=1) name = ["総数"] + list(range(101)) pv3 = pv2.loc[:, name] pv3.to_csv("data1.csv", encoding="utf_8_sig")
Pandas
import pandas as pd df = pd.read_excel("https://www.e-stat.go.jp/stat-search/file-download?statInfId=000013168604&fileKind=0", header=None, skiprows=6) df.head(20) # 英語の行削除 df.drop(df.index[4], inplace=True) # 英語の列削除 df.drop(df.columns[1], axis=1, inplace=True) # 年の「1)」を除去 df.iloc[0,:].replace("1\)", "", regex=True, inplace=True) # 空白文字を除去 df.replace(r"\s", "", regex=True, inplace=True) # 年の平成を除去 df.iloc[0,:].replace(r"平成(\d{2})年", "", regex=True, inplace=True) # 年の欠損値を前の値で補完 df.iloc[0,:].fillna(method="ffill", inplace=True) # 年齢の数字以外を除去 df.iloc[:,0].replace(r"歳(以上)?$", "", regex=True, inplace=True) # タイトル補完 df.iloc[0, 0] = "年" df.iloc[2, 0] = "性別" # データ以外を行・列除去 df1 = df.loc[df.notnull().sum(axis=1) > 2, df.notnull().sum() > 2].copy() # 欠損値を0で補間 df1.fillna(0, inplace=True) # CSVに保存 df1.T.to_csv("data.csv", encoding="utf_8_sig", index=False, header=False) df1
総数
df2 = pd.read_csv("data.csv", index_col=[0,1], header=0) df2.head(10) df2["総数"] - df2.loc[:, "0":"100"].sum(axis=1)
年 | 男 | 女 | 男女計 |
---|---|---|---|
2000 | 0 | -3 | -4 |
2001 | -1 | 1 | -1 |
2002 | 2 | -2 | 1 |
2003 | -3 | 2 | -2 |
2004 | -2 | 2 | -2 |
2005 | 2 | 4 | 2 |
2006 | 2 | 0 | 4 |
2007 | 3 | 2 | -2 |
2008 | -1 | 1 | -2 |
2009 | -2 | -1 | 1 |
2010 | 8 | 4 | 0 |
2011 | 0 | 2 | 1 |
2012 | 1 | 1 | 3 |
2013 | 3 | -2 | 0 |
2014 | 1 | -1 | 5 |
2015 | 0 | 1 | 1 |
男女の計
df3 = pd.read_csv("data.csv", index_col=None, header=0) df3.head(10) df3.drop("総数", axis=1, inplace=True) df3.head() df4 = df3.melt(id_vars=["年", "性別"], var_name="年齢", value_name="人数") df4.head(10) pv4 = df4.pivot_table(index="年", columns="性別", values="人数", aggfunc="sum") pv4["差"] = pv4["男女計"] - pv4["男"] - pv4["女"]
年 | 男 | 女 | 男女計 | 差 |
---|---|---|---|---|
2000 | 62111 | 64818 | 126930 | 1 |
2001 | 62245 | 65046 | 127292 | 1 |
2002 | 62250 | 65185 | 127434 | -1 |
2003 | 62307 | 65313 | 127621 | 1 |
2004 | 62297 | 65390 | 127689 | 2 |
2005 | 62347 | 65415 | 127766 | 4 |
2006 | 62328 | 65440 | 127766 | -2 |
2007 | 62307 | 65459 | 127773 | 7 |
2008 | 62252 | 65440 | 127694 | 2 |
2009 | 62132 | 65381 | 127509 | -4 |
2010 | 62320 | 65726 | 128057 | 11 |
2011 | 62184 | 65613 | 127798 | 1 |
2012 | 62028 | 65485 | 127512 | -1 |
2013 | 61906 | 65390 | 127298 | 2 |
2014 | 61800 | 65283 | 127078 | -5 |
2015 | 61842 | 65252 | 127094 | 0 |
年・年齢
df4["年齢"] = df4["年齢"].astype(int) pv5 = df4.pivot_table(index=["年", "年齢"], columns="性別", values="人数", aggfunc="sum") pv5["集計"] = pv5["男"] + pv5["女"] pv5["差"] = pv5["男女計"] - pv5["集計"]