2015-12-06 2 views
1

Вот мой текущий dataframe:Как создать новые столбцы в dataframe из строки другого столбца?

>>>df = {'most_exhibitions' : pd.Series(['USA (1) Netherlands (5)' , 
'United Kingdom (2)','China (3) India (5) Pakistan (8)','USA (11) India (4)'], index=['a', 'b', 'c','d']), 
       'name' : pd.Series(['Bob', 'Joe', 'Alex', 'Bill'], index=['a', 'b', 'c','d'])} 

>>> df 
    name     most_exhibitions 
a Bob     USA (1) India (5) 
b Joe     United Kingdom (2) 
c Alex  China (3) India (5) USA (8) 
d Bill    USA (11) India (4) 

Я пытаюсь выяснить, как разделить каждую ячейку, а затем, возможно, создать новый столбец из страны и поместить соответствующее количество в правом ряду. Если страна уже является существующим столбцом, я хочу просто поместить счет в правый ряд.

Таким образом, окончательный dataframe будет выглядеть следующим образом:

# name     most_exhibitions   USA United Kingdom China India  
#a Bob     USA (1), India (5)    1         5 
#b Joe     United Kingdom (2)        2 
#c Alex  China (3), India (5), USA (8)    8       3  5 
#d Bill    USA (11), India (4)    11         4 

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

Вот что я сделал до сих пор:

>>>country_rank_df['country_split'] 
= indexed_rankdata['most_exhibitions'].str.split(",").astype(str) 

from collections import defaultdict 
total_dict = defaultdict(list) 

dict2 = defaultdict(list) 
dict3 = defaultdict(list) 
dict4 = defaultdict(list) 
dict5 = defaultdict(list) 
dict6 = defaultdict(list) 

for name, country_count in zip(head_df['name'], head_df['most_exhibitions']): 

    total_dict[name].append(country_count) 

for key, value in total_dict.iteritems(): 
    for line in value: 
     new_line = line.split('(') 
     dict2[key].append(new_line) 

for key, list_outside in dict2.iteritems(): 
    for list_inside in list_outside: 
     for value in list_inside: 
      new_line = value.split(',') 
      dict3[key].append(new_line) 

for key, list_outside in dict3.iteritems(): 
    for list_inside in list_outside: 
     for value in list_inside: 
      new_line = value.split(')') 
      dict4[key].append(new_line) 

for key, list_outside in dict4.iteritems(): 
    for list_inside in list_outside: 
     for value in list_inside: 
      new_line = value.strip() 
      new_line = value.lstrip() 
      dict5[key].append(new_line) 

for key, list_outside in dict5.iteritems(): 
    new_line = filter(None, list_outside) 
    dict6[key].append(new_line) 

>>>dict6['Bob'] 

[['USA', 
    '1', 
    'India', 
    '5']] 

ответ

1

Вы можете попробовать этот подход, который используют в основном string methods. Затем I pivot и fillna dataframe. Я потерял оригинальную колонку most_exhibitions, но я надеюсь, что это не нужно.

import pandas as pd 

df = {'most_exhibitions' : pd.Series(['USA (1) Netherlands (5)' , 
'United Kingdom (2)','China (3) India (5) Pakistan (8)','USA (11) India (4)'], index=['a', 'b', 'c','d']), 
       'name' : pd.Series(['Bob', 'Joe', 'Alex', 'Bill'], index=['a', 'b', 'c','d'])} 

df = pd.DataFrame(df) 
#cange ordering of columns 
df = df[['name', 'most_exhibitions']] 
print df 
# name     most_exhibitions 
#a Bob   USA (1) Netherlands (5) 
#b Joe    United Kingdom (2) 
#c Alex China (3) India (5) Pakistan (8) 
#d Bill    USA (11) India (4) 


#remove '(' and last ')' 
df['most_exhibitions'] = df['most_exhibitions'].str.replace('(', '') 
df['most_exhibitions'] = df['most_exhibitions'].str.strip(')') 

#http://stackoverflow.com/a/34065937/2901002 
s = df['most_exhibitions'].str.split(')').apply(pd.Series, 1).stack() 
s.index = s.index.droplevel(-1) 
s.name = 'most_exhibitions' 
print s 
#a    USA 1 
#a  Netherlands 5 
#b United Kingdom 2 
#c    China 3 
#c    India 5 
#c   Pakistan 8 
#d    USA 11 
#d    India 4 
#Name: most_exhibitions, dtype: object 

df = df.drop(['most_exhibitions'], axis=1) 
df = df.join(s) 
print df 
# name most_exhibitions 
#a Bob    USA 1 
#a Bob  Netherlands 5 
#b Joe United Kingdom 2 
#c Alex   China 3 
#c Alex   India 5 
#c Alex  Pakistan 8 
#d Bill   USA 11 
#d Bill   India 4 

#exctract numbers and convert them to integer 
df['numbers'] = df['most_exhibitions'].str.extract("(\d+)").astype('int') 
#exctract text of most_exhibitions 
df['most_exhibitions'] = df['most_exhibitions'].str.rsplit(' ', n=1).str[0] 
print df 
# name most_exhibitions numbers 
#a Bob    USA  1 
#a Bob  Netherlands  5 
#b Joe United Kingdom  2 
#c Alex   China  3 
#c Alex   India  5 
#c Alex   Pakistan  8 
#d Bill    USA  11 
#d Bill   India  4 

#pivot dataframe 
df = df.pivot(index='name', columns='most_exhibitions', values='numbers') 
#NaN to empty string 
df = df.fillna('') 
print df 
#most_exhibitions India Netherlands Pakistan China USA United Kingdom 
#name                 
#Alex     5      8  3     
#Bill     4        11    
#Bob        5     1    
#Joe                 2 

EDIT:

Я пытаюсь добавить все столбцы в соответствии с рекомендациями по выходу функции merge:

import pandas as pd 

df = {'most_exhibitions' : pd.Series(['USA (1) Netherlands (5)' , 
'United Kingdom (2)','China (3) India (5) Pakistan (8)','USA (11) India (4)'], index=['a', 'b', 'c','d']), 
       'name' : pd.Series(['Bob', 'Joe', 'Alex', 'Bill'], index=['a', 'b', 'c','d'])} 

df = pd.DataFrame(df) 
#cange ordering of columns 
df = df[['name', 'most_exhibitions']] 
print df 
# name     most_exhibitions 
#a Bob   USA (1) Netherlands (5) 
#b Joe    United Kingdom (2) 
#c Alex China (3) India (5) Pakistan (8) 
#d Bill    USA (11) India (4) 

#copy original to new dataframe for joining original df 
df1 = df.reset_index().copy() 

#remove '(' and last ')' 
df['most_exhibitions'] = df['most_exhibitions'].str.replace('(', '') 
df['most_exhibitions'] = df['most_exhibitions'].str.strip(')') 

#http://stackoverflow.com/a/34065937/2901002 
s = df['most_exhibitions'].str.split(')').apply(pd.Series, 1).stack() 
s.index = s.index.droplevel(-1) 
s.name = 'most_exhibitions' 
print s 
#a    USA 1 
#a  Netherlands 5 
#b United Kingdom 2 
#c    China 3 
#c    India 5 
#c   Pakistan 8 
#d    USA 11 
#d    India 4 
#Name: most_exhibitions, dtype: object 

df = df.drop(['most_exhibitions'], axis=1) 
df = df.join(s) 
print df 
# name most_exhibitions 
#a Bob    USA 1 
#a Bob  Netherlands 5 
#b Joe United Kingdom 2 
#c Alex   China 3 
#c Alex   India 5 
#c Alex  Pakistan 8 
#d Bill   USA 11 
#d Bill   India 4 

#exctract numbers and convert them to integer 
df['numbers'] = df['most_exhibitions'].str.extract("(\d+)").astype('int') 
#exctract text of most_exhibitions 
df['most_exhibitions'] = df['most_exhibitions'].str.rsplit(' ', n=1).str[0] 
print df 
# name most_exhibitions numbers 
#a Bob    USA  1 
#a Bob  Netherlands  5 
#b Joe United Kingdom  2 
#c Alex   China  3 
#c Alex   India  5 
#c Alex   Pakistan  8 
#d Bill    USA  11 
#d Bill   India  4 

#pivot dataframe 
df = df.pivot(index='name', columns='most_exhibitions', values='numbers') 
#NaN to empty string 
df = df.fillna('') 
df = df.reset_index() 
print df 
#most_exhibitions name India Netherlands Pakistan China USA United Kingdom 
#0     Alex  5      8  3     
#1     Bill  4        11    
#2     Bob     5     1    
#3     Joe              2 
print df1 
# index name     most_exhibitions 
#0  a Bob   USA (1) Netherlands (5) 
#1  b Joe    United Kingdom (2) 
#2  c Alex China (3) India (5) Pakistan (8) 
#3  d Bill    USA (11) India (4) 
df = pd.merge(df1,df, on=['name']) 
df = df.set_index('index') 
print df 
#  name     most_exhibitions India Netherlands Pakistan \ 
#index                   
#a  Bob   USA (1) Netherlands (5)     5    
#b  Joe    United Kingdom (2)         
#c  Alex China (3) India (5) Pakistan (8)  5      8 
#d  Bill    USA (11) India (4)  4       
# 
#  China USA United Kingdom 
#index       
#a    1     
#b       2 
#c   3      
#d   11     
+0

спасибо @jezrael. Когда я пытаюсь сделать следующее: 'name_exhibitions_df_2 ['most_exhibitions'] = name_exhibitions_df_2 ['most_exhibitions']. Str.rsplit ('', n = 1) .str [0]', я получаю эту ошибку: 'AttributeError: ' Объект StringMethods не имеет атрибута 'rsplit''. Знаете ли вы, почему это так? Я использую Python 2.7.8 и iPython 2.1.0. –

+0

Эта ошибка с вашим образцом? какая версия панд использует 'print pd .__ version__'? – jezrael

+0

Спасибо, что помогли так быстро. Да, это не работает с моим образцом. Версия 0.14.0 –

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