2017-02-07 2 views
0

목표 : 하나의 열이 쉼표로 구분 된 하나의 DataFrame 인 root_df가 있습니다. (예 : "문, 표범, 경례")라는 단어. 그런 다음 다른 DataFrame, freq_df, WORD (string) 및 SCORE (float)의 두 열이있는 곳이 있습니다. 내가하고 싶은 일은 첫 번째 DataFrame, root_df의 열을 기반으로 두 번째 DataFrame, freq_df의 점수로 집계 열을 만드는 것입니다. 내가 한 가지 예를 들어 보겠다. freq_df에서 "door"가있는 행의 점수는 342388이고 ​​"panther"라는 단어는 DataFrame에 전혀 없으며 "salute"는 9238.07 점입니다. 따라서 root_df의 열은 342388 + 9238.07이되며 이는 351626.07입니다.df.apply()는 내 df의 일부에서 작동하지만 "TypeError : float object is iterable"을 전체 df에서 반환합니다.

문제 : 내 데이터의 하위 집합에() .apply 사용하여이 작업을 수행 할 수 있었다, 그러나 나는 전체 데이터에이를 얻을 수하려고 할 때 설정이 반환 "형식 오류는 '부동'개체가 아닙니다 iterable "입니다. 나는 이것이 "스플릿 단어"열의 NaN 인 것으로 생각했기 때문에 모든 NaN을 도움이되는지 확인하고 새로운 오류를 반환했는지 "TypeError :("unhashable type : 'list' ", '인덱스 분할 단어'에서 발생했습니다. '). 왜 이것이 내 데이터의 하위 집합에서 작동하지만 모든 것이 작동하는지 혼란 스럽습니다. 모든 Series에는 동일한 데이터 유형이 있다고 생각했습니다. 누군가 일어나는 일을 설명 할 수 있습니까? 오류를 반환하는 행을 반환 할 수있는 방법이 있습니까? 어떤 도움을 주시면 감사하겠습니다.

위키피디아 테이블에서 가져온 DataFrame을 포함하여 전체 코드가 문제를 재현합니다. 그들의 질문에 대한 질문이나 문제가 있다면 알려주십시오.

import numpy as np 
import pandas as pd 
import urllib.request 

def get_score(field): 
    words_list = [] 
    for word in field: 
     words_list.append(word) 

    mask = freq_df['Word'].isin(words_list) 

    return freq_df.loc[mask, 'Count (per billion)'].sum() 

#Root DataFrame 
root_urls = [r"https://en.wikipedia.org/wiki/List_of_Greek_and_Latin_roots_in_English/A%E2%80%93G", 
     r"https://en.wikipedia.org/wiki/List_of_Greek_and_Latin_roots_in_English/H%E2%80%93O", 
     r"https://en.wikipedia.org/wiki/List_of_Greek_and_Latin_roots_in_English/P%E2%80%93Z"] 

root_dfs = [] 

for url in root_urls: 
    dfs = pd.read_html(url, header=0) 
    for i, df in enumerate(dfs): 
     if df.shape[1] != 5: 
      print('Deleted below DataFrame(s):\n', dfs[i].head()) 
      del dfs[i] 
    root_dfs.extend(dfs) 

root_df = pd.concat(root_dfs, ignore_index=True) 
root_df.replace(to_replace="\[.*?]", value="", regex=True, inplace=True) 

#Frequency DataFrame 
url = r"https://en.wiktionary.org/wiki/Wiktionary:Frequency_lists/PG/2006/04/1-10000" 

freq_dfs = pd.read_html(url, header=0) 

freq_df = pd.concat(freq_dfs) 

#Succesful use of apply 
test = root_df.head().copy() 
a = pd.DataFrame(columns=test.columns) 
a.loc[0] = ['Test', 'Test', 'Test', 'Test', 'door, panther, salute'] # Adding the exact example I gave above 
test = pd.concat([test, a], ignore_index=True) 
test['Split words'] = test['English examples'].str.split(', ') 

test_score = test['Split words'].apply(get_score) # LINE IN QUESTION : SUCCESS 
print("\nSuccesful test:\n\n", test_score) 

#Unsuccesful use of apply 
root_df['Split words'] = root_df['English examples'].str.split(', ') 
score = root_df['Split words'].apply(get_score) # LINE IN QUESTION : FAIL 
print(score) 

답변

1

나는 apply을 사용할 필요가 없다고 생각합니다. 당신은 하나의 긴 시리즈 English Examples에있는 모든 단어를 가져온 다음 freq_df에서 값을 매핑 할 map를 사용하고 English Examples

# First get the score mapping series 
score = freq_df.set_index('Word')['Count (per billion)'] 

# use stack to make one long series of words from 
# english examples 
stacked_words = root_df['English examples'].str.split(',\s*', expand=True).stack() 

# map all the english example words to their score 
# and then sum up each group(original row) 
stacked_words.map(score).groupby(level=0).sum().fillna(0) 

0  56157.78 
1   0.00 
2   0.00 
3   0.00 
4   0.00 
5   0.00 
6   0.00 
7   0.00 
8   0.00 
9   0.00 
10   0.00 
11   0.00 
12  11422.40 
13  190547.67 
.... 
+0

감사의 각 원본 목록을 요약 할 수 있습니다! 내 원래의 생각의 기차는 바꾸기와 같은 것을 사용하려했지만 알아 내지 못했기 때문에 .apply()를 사용해야했습니다. 그냥 .map()을 올바르게 이해했는지를 확인하기 위해 기본적으로 두 개의 Series가 필요합니다. 첫 번째 계열의 값을 가져 와서 두 번째 계열의 값으로 바꿉니다. 여기서 Series1 value = Series2 index입니다. 그게 맞습니까? –

관련 문제