2015-06-17 6 views
3

У меня есть файл CSV и формат моих данных выглядит следующим образом:Как я могу изменить свои данные в CSV-файле и изменить строки и столбцы?

Countries variable 1995 1996 1997 1998 1999 
    USA  GDP  10  11 12 12  13 
    USA  Inf  100 120 130 120 110 
    USA  Trade 200 220 210 235 250 
    GER  GDP  8  9  9.5 10  10.5 
    GER  Inf  100 105 107 109 111 
    GER  Trade 150 156 149 165 167 

Я намерен изменить свои данные и изменить его на что-то вроде:

Countries Years GDP Inf Trade 
    USA  1995  10 100 200 
    USA  1996  11 120 220 
    USA  1997  12 130 210 
    USA  1998  12 120 235 
    USA  1999  13 110 250 
    GER  1995  8  100 150 
    GER  1996  9  105 156 
    GER  1997  9.5 107 149 
    GER  1998  10 109 165 
    GER  1999  10.5 111 167 

Я не имею представления о Я могу сделать это в Python. Я импортировал свои данные в pandas, но единственное, что можно сделать на данных, - это перенос столбца и строк, который не тот, который я ищу. Также, используя csv.writerow, я не смог изменить свои данные.

ответ

2

Если у вас есть свои данные в список списков:

>>> for line in data: 
...  print('\t'.join(line)) 
... 
USA GDP 10 11 12 12 13 
USA Inf 100 120 130 120 110 
USA Trade 200 220 210 235 250 
GER GDP 8 9 9.5 10 10.5 
GER Inf 100 105 107 109 111 
GER Trade 150 156 149 165 167 

с помощью следующего кода:

from collections import defaultdict 
data2 = defaultdict(dict) 
for line in data: 
    for i, year in ((2,1995),(3,1996),(4,1997),(5,1998),(6,1999)): 
     data2[(line[0], year)][line[1]] = line[i] 
data3 = [[i,j]+[data2[(i,j)][k] for k in ('GDP','Inf','Trade')] for i,j in data2] 
for line in sorted(data3): 
    print(line) 

вы получите:

['GER', 1995, '8', '100', '150'] 
['GER', 1996, '9', '105', '156'] 
['GER', 1997, '9.5', '107', '149'] 
['GER', 1998, '10', '109', '165'] 
['GER', 1999, '10.5', '111', '167'] 
['USA', 1995, '10', '100', '200'] 
['USA', 1996, '11', '120', '220'] 
['USA', 1997, '12', '130', '210'] 
['USA', 1998, '12', '120', '235'] 
['USA', 1999, '13', '110', '250'] 
+0

Иметь хороший день! –

+0

@mescalinum спасибо за ваше время – homayoun

3

Вы можете использовать Ordereddict группе данные:

import csv 
from collections import OrderedDict,defaultdict 
from itertools import islice 
with open("out.csv") as f: 
    od = OrderedDict() 
    r = csv.reader(f, delimiter=" ") 
    header = next(r) 
    years = header[2:] 
    zipped = zip(*r) 
    countries = OrderedDict.fromkeys(zipped[0]).keys() # next(zipped) python3 
    it = iter(countries) 
    for row in zip(*zipped[1:]): # for row in zip(*zipped) python3 
     if row[0] == "GDP": 
      key = next(it) 
      od.setdefault(key, defaultdict(list)) 
      od[key]["Years"] = years 
      od[key]["Country"] = [key] * len(years) 
     od[key][row[0]].extend(islice(row,1,None)) 

Выход:

OrderedDict([('USA', defaultdict(<type 'list'>, {'GDP': ['10', '11', '12', '12', '13'], 'Inf': ['100', '120', '130', '120', '110'], 'Years': ['1995', '1996', '1997', '1998', '1999'], 'Trade': ['200', '220', '210', '235', '250']})), ('GER', defaultdict(<type 'list'>, {'GDP': ['8', '9', '9.5', '10', '10.5'], 'Inf': ['100', '105', '107', '109', '111'], 'Years': ['1995', '1996', '1997', '1998', '1999'], 'Trade': ['150', '156', '149', '165', '167']}))]) 

Кто-то более опытный в панд будет иметь возможность получить более хороший способ сделать это не сомневаюсь, но это будет по крайней мере, создать dataframe:

df = pd.DataFrame(columns=["Country","Years","GDP","Inf","Trade"]) 

for k,v in od.items(): 
    df_temp = pd.DataFrame((v[k] for k in ["Country","Years","GDP","Inf","Trade"]),["Country","Years","GDP","Inf","Trade"]).transpose() 
    f = df.append(df_temp,ignore_index=True) 
print(df) 

Выход:

Country Years GDP Inf Trade 
0  USA 1995 10 100 200 
1  USA 1996 11 120 220 
2  USA 1997 12 130 210 
3  USA 1998 12 120 235 
4  USA 1999 13 110 250 
5  GER 1995  8 100 150 
6  GER 1996  9 105 156 
7  GER 1997 9.5 107 149 
8  GER 1998 10 109 165 
9  GER 1999 10.5 111 167 

Если файл больше, вы также можете создать кадр данных, когда вы идете, и каждый раз перезагружать OrderedDict, чтобы избежать сохраняя все данные в dict также, вам просто нужно добавить последнюю группу вне основного кода, мы также можем использовать itertools.islice, чтобы получить все фрагменты и использовать itertools.izip для zip при использовании python2:

import csv 
from collections import OrderedDict,defaultdict 
from itertools import islice,izip 

df = pd.DataFrame(columns=["Country","Years","GDP","Inf","Trade"]) 
with open("out.csv") as f: 
    od = OrderedDict() 
    r = csv.reader(f, delimiter=" ") 
    header = next(r) 
    years = header[2:] 
    zipped = izip(*r) 
    countries = OrderedDict.fromkeys(next(zipped)).keys() 
    it = iter(countries) 
    for row in izip(*zipped): 
     if row[0] == "GDP": 
      if od: # make sure it is not the first line 
       for k, v in od.items(): 
        df_temp = pd.DataFrame((v[k] for k in ["Country","Years","GDP","Inf","Trade"]), ["Country","Years","GDP","Inf","Trade"]).transpose() 
        df = df.append(df_temp, ignore_index=True) 
        od = OrderedDict() 
      key = next(it) 
      od.setdefault(key, defaultdict(list)) 
      od[key]["Years"] = years 
      od[key]["Country"] = [key] * len(years) 
     od[key][row[0]].extend(islice(row, 1, None)) 

for k,v in od.items(): 
     df_temp = pd.DataFrame((v[k] for k in ["Country","Years","GDP","Inf","Trade"]), ["Country","Years","GDP","Inf","Trade"]).transpose() 
     df = df.append(df_temp, ignore_index=True) 


print(df) 

Который снова должен дать тот же результат:

Country Years GDP Inf Trade 
0  USA 1995 10 100 200 
1  USA 1996 11 120 220 
2  USA 1997 12 130 210 
3  USA 1998 12 120 235 
4  USA 1999 13 110 250 
5  GER 1995  8 100 150 
6  GER 1996  9 105 156 
7  GER 1997 9.5 107 149 
8  GER 1998 10 109 165 
9  GER 1999 10.5 111 167 
+1

Cunninghm спасибо за ваше время – homayoun

2

Этот ответ будет много, как @ AmiTavory они удаляются ответ (используя unstack вместо pivot_table, но они эквивалентны здесь) с одним дополнительным шагом в то конец:

df2 = pd.melt(df, id_vars=["Countries", "variable"], var_name="Years") 
df2 = df2.set_index(["Countries", "Years", "variable"]).unstack().reset_index() 
df2.columns = [x[1] if x[1] else x[0] for x in df2.columns] 

производит

In [149]: df2 
Out[149]: 
    Countries Years GDP Inf Trade 
0  GER 1995 8.0 100 150 
1  GER 1996 9.0 105 156 
2  GER 1997 9.5 107 149 
3  GER 1998 10.0 109 165 
4  GER 1999 10.5 111 167 
5  USA 1995 10.0 100 200 
6  USA 1996 11.0 120 220 
7  USA 1997 12.0 130 210 
8  USA 1998 12.0 120 235 
9  USA 1999 13.0 110 250 

Это работает, потому что первое мы создаем топленое версию кадра:

In [160]: df2 = pd.melt(df, id_vars=["Countries", "variable"], var_name="Years") 

In [161]: df2 
Out[161]: 
    Countries variable Years value 
0  USA  GDP 1995 10.0 
1  USA  Inf 1995 100.0 
2  USA Trade 1995 200.0 
3  GER  GDP 1995 8.0 
4  GER  Inf 1995 100.0 
5  GER Trade 1995 150.0 
6  USA  GDP 1996 11.0 
[...] 

, а затем мы устанавливаем индекс и поместить значение:

In [166]: df2 = df2.set_index(["Countries", "Years", "variable"]).unstack().reset_index() 

In [167]: df2 
Out[167]: 
     Countries Years value   
variable     GDP Inf Trade 
0    GER 1995 8.0 100 150 
1    GER 1996 9.0 105 156 
2    GER 1997 9.5 107 149 
3    GER 1998 10.0 109 165 
4    GER 1999 10.5 111 167 
5    USA 1995 10.0 100 200 
6    USA 1996 11.0 120 220 
7    USA 1997 12.0 130 210 
8    USA 1998 12.0 120 235 
9    USA 1999 13.0 110 250 

, что почти то, что мы хотим, но столбцы слишком mplicated.Мы можем исправить это:

In [168]: df2.columns 
Out[168]: 
MultiIndex(levels=[['value', 'Years', 'Countries'], ['GDP', 'Inf', 'Trade', '']], 
      labels=[[2, 1, 0, 0, 0], [3, 3, 0, 1, 2]], 
      names=[None, 'variable']) 

In [169]: df2.columns = [x[1] if x[1] else x[0] for x in df2.columns] 

In [170]: df2 
Out[170]: 
    Countries Years GDP Inf Trade 
0  GER 1995 8.0 100 150 
1  GER 1996 9.0 105 156 
2  GER 1997 9.5 107 149 
3  GER 1998 10.0 109 165 
4  GER 1999 10.5 111 167 
5  USA 1995 10.0 100 200 
6  USA 1996 11.0 120 220 
7  USA 1997 12.0 130 210 
8  USA 1998 12.0 120 235 
9  USA 1999 13.0 110 250 
+0

спасибо, он отлично работает, и я использовал его. – homayoun

1

Я скопировал ваши данные в электронную таблицу. Возможно, переименование не обязательно, но я думаю, что в столбце с именем variable возникла ошибка. Кроме того, я не проверял, является ли это наименьшим потреблением ОЗУ.

import pandas as pd 
import numpy as np 
df = pd.read_excel('df_countries.xls','Sheet1') 
df.columns=['countries','var','1995','1996','1997','1998','1999'] 
df_new = pd.melt(df,id_vars=['countries','var']) 
df_new.columns = ['countries','var','year','data'] 
df_new.set_index(['countries','year','var']).unstack('var') 

enter image description here

+0

спасибо, он отлично работает. – homayoun

Смежные вопросы