2017-09-01 3 views
1

私は数千のオンライン記事のURLを含む「リンク」列のデータフレームを持っています。各観測にはURLが1つあります。一致する行に辞書キーを割り当てながら、辞書値を使ってデータフレームをフィルタリングしますか?

urls_list = ['http://www.ajc.com/news/world/atlan...', 
      'http://www.seattletimes.com/sports/...', 
      'https://www.cjr.org/q_and_a/washing...', 
      'https://www.washingtonpost.com/grap...', 
      'https://www.nytimes.com/2017/09/01/...', 
      'http://www.oregonlive.com/silicon-f...'] 

df = pd.DataFrame(urls_list,columns=['Links']) 

私はさらにパブリケーション名キーとドメイン名の値としてとしてが含まれている辞書を持っています。

私は同時にで がに辞書のキーにパブリケーション名を割り当てながら「リンク」列には、辞書の値にドメインが含まれているもののみの観測を取得するためにデータフレームをフィルタリングしたい
urls_dict = dict({'Atlanta Journal-Constitution':'ajc.com', 
        'The Washington Post':'washingtonpost.com', 
        'The New York Times':'nytimes.com'}) 

新しい列「出版物」。私が思ったのは、以下のコードを使って 'Publication'カラムを作成し、そのカラムからNoneを落として、事実の後にデータフレームをフィルタリングすることです。

pub_list = [] 

for row in df['Links']: 
    for k,v in urls_dict.items(): 
     if row.find(v) > -1: 
      publication = k 
     else: 
      publication = None 
     pub_list.append(publication) 

しかし、私は見返りに取得リストpub_list - 私が意図したものを行うように見える一方では - 私のデータフレームの長の3倍です。誰かが上記のコードを修正する方法を提案できますか?または、(1)辞書値(ドメイン名)を使用して自分のデータフレームの「リンク」列をフィルタリングすること、(2)辞書キー(パブリケーション名)の新しい「パブリケーション」列を作成すること、 ? (dfは、簡潔にするために1列のみで、ここで作成されていることに注意してください。実際のファイルは、私が上でフィルタリングする列を指定できるようにする必要があり、それによって多くの列を持っているとします。)

編集:私はしたかったいくつかの説明を与えますRagingRooseveltの答え。私はいくつかのドメインが正確に一致しないかもしれないので、マージの使用を避けたい。たとえば、ajc.comとすると、myajc.comをキャプチャできます。washingtonpost.comと入力すると、live.washingtonpost.comなどのサブドメインも使用したいと考えています。したがって、私はstr.contains()find()、またはinの演算子を使用して、「文字列内の部分文字列を見つける」ソリューションを期待していました。

答えて

0

私が列をクリーンアップし、空白行を削除するには、いくつかの追加のデータフレームの操作で(ネストされたリストの内包表記を使用して、そしてその代わりに)ネストされた辞書内包表記を使用してそれを把握することができました。

# First converting dict to a list of lists 
urls_list_of_lists = list(map(list,urls_dict.items())) 

# Nested list comprehension using 'in' operator 
df['Publication'] = [[item[0] for item in urls_list_of_lists if item[1] in row] for row in df['Links']] 

# Format the 'Publication' column to get rid of duplicate brackets 
df['Publication'] = df['Publication'].astype(str).str.strip('[]') 

# Remove blank rows from 'Publication' column 
df = df[df['Publication'] != ''] 
ネストされたリスト内包を使用して、同様

df['Publication'] = [{k: k for k,v in urls_dict.items() if v in row} for row in df['Links']] 

# Format the 'Publication' column to get rid of duplicate 'key' values 
df['Publication'] = df['Publication'].astype(str).str.strip('{}').str.split(':',expand=True)[0] 

# Remove blank rows from 'Publication' column 
df = df[df['Publication'] != ''] 

ネスト辞書理解(又は、より具体的には、リスト内包の内側にネストされた辞書理解)を使用

1

は、ここで私がしたいものです。

  1. 使用DataFrame.applyだけのドメインを含む、あなたのデータフレームに新しい列を追加します。

  2. ドメインフィールドに2つのデータフレームをマージするには、DataFrame.mergehow='inner'オプション付き)を使用します。

それは、彼らはただの列または行を反復していると一般的に、よりきれいに同じことを行いDATAFRAME方法があるかどうデータフレームにものを行うために、ループを使用するように少し汚いです。

必要に応じて、この例を拡張することができます。

編集これは、次のようになります。私はドメインキャプチャのためにかなりひどい正規表現を使用していることに注意してください。

def domain_extract(row): 
    s = row['Links'] 
    p = r'(?:(?:\w+)?(?::\/\/)(?:www\.)?)?([A-z0-9.]+)\/.*' 
    m = re.match(p, s) 
    if m is not None: 
     return m.group(1) 
    else: 
     return None 

df['Domain'] = df.apply(domain_extract, axis=1) 

dfo = pd.DataFrame({'Name': ['Atlanta Journal-Constitution', 'The Washington Post', 'The New York Times'], 'Domain': ['ajc.com', 'washingtonpost.com', 'nytimes.com']}) 

df.merge(dfo, on='Domain', how='inner')[['Links', 'Domain', 'Name']] 
+0

ありがとうございます。これはうまくいきますが、ドメインの一部が一致していない可能性があるため、 'merge'を使用しないでください。たとえば、 'ajc.com'では' myajc.com'をキャプチャできますし、 'washingtonpost.com'では' live.washingtonpost.com'のようなサブドメインをよくしたがって、いくつかの柔軟性を追加するために、str.contains()またはfind()を使用した「文字列内の部分文字列の検索」ソリューションを期待していました。 – dmitriys

+0

ファジーマッチングが可能であるように見える https://stackoverflow.com/questions/13636848/is-it-possible-to-do-fuzzy-match-merge-with-python-pandas – RagingRoosevelt

関連する問題