2013-11-11 2 views
1

(я сосу на эти вопросы титулов ...)Установка панды условия для столбцов по строкам, Python 2.7

Таким образом, я получил 90% пути через очень трудоемкий процесс обучения с пандами, но у меня есть осталось одно. Позвольте мне показать пример (фактический оригинал разделенный запятыми CSV, который имеет много больше строк):

Name Price Rating URL    Notes1  Notes2   Notes3 
Foo  $450  9   a.com/x   NaN   NaN    NaN 
Bar  $99  5   see over   www.b.com Hilarious   Nifty 
John $551  2   www.c.com   Pretty  NaN    NaN 
Jane $999  8   See Over in Notes Funky  http://www.d.com Groovy 

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

Я хотел бы сделать несколько вещей здесь: сначала переместите веб-сайты из любого столбца Notes в URL; во-вторых, сверните все столбцы заметок в один столбец с новой строкой между ними. Так что это (Нан удалены, так как панды делает меня для того, чтобы использовать их в df.loc):

Name Price Rating URL    Notes1  
Foo  $450  9   a.com/x    
Bar  $99  5   www.b.com   Hilarious 
               Nifty 
John $551  2   www.c.com   Pretty 
Jane $999  8   http://www.d.com Funky 
               Groovy 

Я получил там частично это сделать:

df['URL'] = df['URL'].fillna('') 
df['Notes1'] = df['Notes1'].fillna('') 
df['Notes2'] = df['Notes2'].fillna('') 
df['Notes3'] = df['Notes3'].fillna('') 
to_move = df['URL'].str.lower().str.contains('see over') 
df.loc[to_move, 'URL'] = df['Notes1'] 

То, что я не знаю, как чтобы найти столбец Notes с www или .com. Если я, например, попытаться использовать мой вышеупомянутый метод в качестве условия, например:

if df['Notes1'].str.lower().str.contains('www'): 
    df.loc[to_move, 'URL'] = df['Notes1'] 

я вернусь ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() Но добавление .any() или .all() имеет очевидный недостаток, что они не дают мне то, что я ищу для: с любой, например, каждая строка, соответствующая требованию to_move в URL-адресе, получит все, что есть в Notes1. Мне нужно, чтобы проверка выполнялась по строкам. По тем же причинам я даже не могу начать разворачивать столбцы Notes (и я не знаю, как проверить ненулевые пустые ячейки ячеек, либо проблему, которую я создал на этом этапе).

Где он находится, я знаю, что мне также нужно перемещать Notes2 в Notes1, Notes3 в Notes2 и '' в Notes3, когда выполняется первое условие, потому что мне не нужны оставшиеся URL-адреса в столбцах Notes. Я уверен, что у панд есть более простые маршруты, чем то, что я делаю, потому что это панды, и когда я пытаюсь сделать что-либо с пандами, я узнаю, что это можно сделать в одной строке вместо моих 20 ...

(PS, мне все равно, остались ли пустые столбцы Notes2 и Notes3, b/c Я не буду использовать их в своем CSV-импорт на следующем шаге, хотя я всегда могу узнать больше, чем мне нужно)

UPDATE: Итак, я разобрался в сложное многословное решение, используя мою логику pythas не-pandas один шаг за раз. Я придумал это (те же первые пять строк выше, минус df.loc линии):

url_in1 = df['Notes1'].str.contains('\.com') 
url_in2 = df['Notes2'].str.contains('\.com') 
to_move = df['URL'].str.lower().str.contains('see-over') 
to_move1 = to_move & url_in1 
to_move2 = to_move & url_in2 
df.loc[to_move1, 'URL'] = df.loc[url_in1, 'Notes1'] 
df.loc[url_in1, 'Notes1'] = df['Notes2'] 
df.loc[url_in1, 'Notes2'] = '' 
df.loc[to_move2, 'URL'] = df.loc[url_in2, 'Notes2'] 
df.loc[url_in2, 'Notes2'] = '' 

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

ответ

1

Я все еще изучаю панды, поэтому некоторые части этого кода могут быть не столь изящными, но общая идея - получить все столбцы заметок, найти все URL-адреса там, объединить их с колонкой URL, а затем конкатюровать оставшиеся заметки в Notes1 column:

import pandas as pd 
import numpy as np 
import pandas.core.strings as strings 

# Just to get first notnull occurence 
def geturl(s): 
    try: 
     return next(e for e in s if not pd.isnull(e)) 
    except: 
     return np.NaN 

df = pd.read_csv("d:/temp/data2.txt") 

dfnotes = df[[e for e in df.columns if 'Notes' in e]] 

#  Notes1   Notes2 Notes3 
# 0  NaN    NaN  NaN 
# 1 www.b.com   Hilarious Nifty 
# 2  Pretty    NaN  NaN 
# 3  Funky http://www.d.com Groovy 

dfurls = dfnotes.apply(lambda x: x.str.contains('\.com'), axis=1) 
dfurls = dfurls.fillna(False).astype(bool) 

# Notes1 Notes2 Notes3 
# 0 False False False 
# 1 True False False 
# 2 False False False 
# 3 False True False 

turl = dfnotes[dfurls].apply(geturl, axis=1) 

df['URL'] = np.where(turl.isnull(), df['URL'], turl) 
df['Notes1'] = dfnotes[~dfurls].apply(lambda x: strings.str_cat(x[~x.isnull()], sep=' '), axis=1) 

del df['Notes2'] 
del df['Notes3'] 

df 
# Name Price Rating    URL   Notes1 
# 0 Foo $450  9   a.com/x     
# 1 Bar $99  5   www.b.com Hilarious Nifty 
# 2 John $551  2   www.c.com   Pretty 
# 3 Jane $999  8 http://www.d.com  Funky Groovy 
Смежные вопросы