在循环中创建多个数据帧

时间:2017-10-18 08:30:13

标签: python pandas

我有人口数据。我想为每个州和年创建单独的数据帧。这个想法如下:

for i in province_id:
    for j in year:
         sub_data_i_j = data[(data.provid==i) &(data.wave==j)]

但是,我不确定如何动态生成sub_data_i_j。

3 个答案:

答案 0 :(得分:2)

我认为最好是使用groupby创建dictionary of DataFrames,然后先boolean indexing过滤:

df = pd.DataFrame({'A':list('abcdef'),
                   'wave':[2004,2005,2004,2005,2005,2004],
                   'C':[7,8,9,4,2,3],
                   'D':[1,3,5,7,1,0],
                   'E':[5,3,6,9,2,4],
                   'provid':list('aaabbb')})

print (df)
   A  C  D  E provid  wave
0  a  7  1  5      a  2004
1  b  8  3  3      a  2005
2  c  9  5  6      a  2004
3  d  4  7  9      b  2005
4  e  2  1  2      b  2005
5  f  3  0  4      b  2004


province_id = ['a','b']
year = [2004]
df = df[(df.provid.isin(province_id)) &(df.wave.isin(year))]
print (df)
   A  C  D  E provid  wave
0  a  7  1  5      a  2004
2  c  9  5  6      a  2004
5  f  3  0  4      b  2004

dfs = {'{0[0]}_{0[1]}'.format(i) : x for i, x in df.groupby(['provid','wave'])}

另一种解决方案:

dfs = dict(tuple(df.groupby(df['provid'] + '_' + df['wave'].astype(str))))
print (dfs)
{'a_2004':    A  C  D  E provid  wave
0  a  7  1  5      a  2004
2  c  9  5  6      a  2004, 'b_2004':    A  C  D  E provid  wave
5  f  3  0  4      b  2004}

最后,您可以选择每个DataFrame:

print (dfs['b_2004'])
   A  C  D  E provid  wave
5  f  3  0  4      b  2004

您的答案应该改为:

sub_data = {}
province_id = ['a','b']
year = [2004]
for i in province_id:
    for j in year:
         sub_data[i + '_' + str(j)] = df[(df.provid==i) &(df.wave==j)]

print (sub_data)
{'a_2004':    A  C  D  E provid  wave
0  a  7  1  5      a  2004
2  c  9  5  6      a  2004, 'b_2004':    A  C  D  E provid  wave
5  f  3  0  4      b  2004}

答案 1 :(得分:1)

我的建议:

import io
import pandas as pd
from collections import defaultdict

string = u"""province_id,wave,value
1,2014,10
1,2014,10
1,2013,10
2,2010,10
3,2010,10"""

df = pd.read_csv(io.StringIO(string))

# Output:
d = defaultdict(dict)

# This splits the dataframe by province_id and wave
dfs = df.groupby(["province_id","wave"])

# Loop through the dataframes and stucture them
for ind,df in dfs:
    d[ind[0]][ind[1]] = df

生成的字典结构如下所示:

{
  "1": {
    "2013": "dataframe: 1 2013", 
    "2014": "dataframe: 1 2014"
  }, 
  "2": {
    "2010": "dataframe: 2 2010"
  }, 
  "3": {
    "2010": "dataframe: 3 2010"
  }
}

您可以通过例如:

访问数据帧

d [1] [2013]

答案 2 :(得分:1)

这应该这样做:

for i in province_id:
    for j in year:
        locals()['sub_data_{}_{}'.format(i,j)] = data[(data.provid==i) & (data.wave==j)]

我最初建议使用exec,出于安全原因,这通常不被视为最佳做法。话虽如此,如果你的代码没有暴露给任何有恶意的人,那应该没问题,为了完整起见,我会把它留在这里:

for i in province_id:
    for j in year:
        exec "sub_data_{}_{} = data[(data.provid==i) & (data.wave==j)]".format(i,j)

然而,对于大多数用例,使用某种类型的集合可能更好,例如字典,因为在代码的后续部分引用动态生成的变量名称会很麻烦。它也是一个单行:

data_dict = {key:g for key,g in data.groupby(['provid','wave'])}