-1

拥有一个托管复合名称(学校名称)的 dataFrame 列,我有兴趣查看学校名称的每个单词并找到它相对于所有 dataFrame 列的位置。我使用了以下方法:

创建另一列,该列是一列,并使用startswith(word) 和endswith(word) 为每个DataFrame 行迭代每个单词。这种方法有效并在小数据集中提供了正确的结果:

Data=[[0,'ABC SCHOOL BOARDING',['ABC','SCHOOL','BOARDING']],
      [1,'UNIVERSITY BOARDING INSTITUTE',['UNIVERSITY','BOARDING','INSTITUTE']],
      [2,'MARIE INSTITUTE SCHOOL',['MARIE', 'INSTITUTE','SCHOOL']],
      [3,'RALPH ELEMENTARY SCHOOL',['RALPH','ELEMENTARY','SCHOOL']],
      [4,'BOARDING SCHOOL',['BOARDING','SCHOOL']]]

df=pd.DataFrame(Data, columns=['id','name', 'name_list'])
df_allWords = pd.DataFrame(columns=['word','classification','counter'])

df2 = pd.DataFrame(columns=['word','classification'])

for index, row in df.iterrows():
    for word in row.name_list:
        df_start=df[(df['name'].str.startswith(word))]
        start_length=len(df_start)

        df_end=df[(df['name'].str.endswith(word))]
        end_length=len(df_end)

        if (start_length>0):
            df2=df2.append(pd.DataFrame({'word':[word], 'classification':['start']}))
        if (end_length>0):
            df2=df2.append(pd.DataFrame({'word':[word], 'classification':['end']}))
        if (end_length<1 and start_length<1):
            df2=df2.append(pd.DataFrame({'word':[word], 'classification':['none']}))

print(df)
print("----")

print(df2)
print("----")

count_series=df2.groupby(['word','classification']).size()
df_count = count_series.to_frame(name = 'counter').reset_index()
df2 = df_count

df2

我需要遍历 DataFrame 中行的每个单词,以找到该单词相对于 DataFrame 中所有行的位置。然后,运行上述代码段后,您可以获得以下信息:

    word    classification  counter
0   ABC start   1
1   BOARDING    end 3
2   BOARDING    start   3
3   ELEMENTARY  none    1
4   INSTITUTE   end 2
5   MARIE   start   1
6   RALPH   start   1
7   SCHOOL  end 4
8   UNIVERSITY  start   1

但是,如果我在 50 万行数据帧中应用以前的方法,它会永远延迟。超过 8 小时后,我无法完成该过程。

避免迭代结束的最佳方法应该是什么row.name_list?我应该看看另一种方法吗?


更新

第二种方法:添加 apply 为每一行运行一个函数

考虑相同的数据框:

Data=[[0,'ABC SCHOOL BOARDING',['ABC','SCHOOL','BOARDING']],
      [1,'UNIVERSITY BOARDING INSTITUTE',['UNIVERSITY','BOARDING','INSTITUTE']],
      [2,'MARIE INSTITUTE SCHOOL',['MARIE', 'INSTITUTE','SCHOOL']],
      [3,'RALPH ELEMENTARY SCHOOL',['RALPH','ELEMENTARY','SCHOOL']],
      [4,'BOARDING SCHOOL',['BOARDING','SCHOOL']]]

df=pd.DataFrame(Data, columns=['id','name', 'name_list'])
df_class = pd.DataFrame(columns=['word','classification'])

我试图通过已有两个数据框来解决所述问题,一个用于起始词,另一个用于结束词删除重复项。然后,在一个函数中,我遍历包含名称列表的列,并与两个数据帧(开始、结束)进行比较:

def classify(row, df_start, df_end):
    df = pd.DataFrame(columns=['word','classification'])
    for word in row.name_list:
        flag=False
        if word in df_start.values:
            df=df.append(pd.DataFrame({'word':[word], 'classification':['start']}))
            flag=True
        if word in df_end.values:
            df=df.append(pd.DataFrame({'word':[word], 'classification':['end']}))
            flag=True
        if (not flag):
            df=df.append(pd.DataFrame({'word':[word], 'classification':['none']}))
    return df

然后返回一个包含单词和分类的数据框。

该函数的调用方式如下:

df_start=pd.DataFrame(columns=['name'])
df_end=pd.DataFrame(columns=['name'])
df_start= df.name.str.split().str.get(0).drop_duplicates(keep="last")
df_end= df.name.str.split().str.get(-1).drop_duplicates(keep="last")

df_class = df.apply(classify, args=[df_start, df_end],axis=1)

但是,由两列(单词、分类)组成的数据帧作为序列而不是数据帧接收。我想知道在使用 apply 时接收为每一行生成的数据帧并将它们添加到单个数据帧中的正确方法是什么。

在此之后,我将按单词和分类按 Dataframe 分组以添加计数器。

感谢您的宝贵贡献:)

4

1 回答 1

0

我认为这样做的最终目的是将每个学校名称的第一个和最后一个单词放入一个新的 DF 中。如果是这样,你的name_list就是多余的。此外,您的逻辑正在执行大量df 开销,这些开销应该通过简单的字符串操作来完成。

重新提出您的问题:对于您的学校列表中的每个字符串,您需要第一个和最后一个单词,并用学校索引标记。

Data=[[0,'ABC SCHOOL BOARDING',['ABC','SCHOOL','BOARDING']],
      [1,'UNIVERSITY CALIFORNIA INSTITUTE',['UNIVERSITY','CALIFORNIA','INSTITUTE']],
      [2,'MARIE JOSEPH HIGH SCHOOL',['MARIE', 'JOSEPH','HIGH','SCHOOL']],
      [3,'RALPH ELEMENTARY SCHOOL DISTRICT',['RALPH','ELEMENTARY','SCHOOL','DISTRICT']],
      [4,'UNIVERSAL SCHOOL ADMINISTRATION',['UNIVERSAL','SCHOOL','ADMINISTRATION']]]

# extract just the school names; I expect that this is the original list
school_list = [school[1] for school in Data]

# Split the name, and extract the first and last words.
# Label with the school's index in the list.
# Yes, this has a redundant "split"; you can make this a loop or vectorized operation.
word_list = [((idx, school_name.split()[0]), (idx, school_name.split()[-1]))
              for idx, school_name in enumerate(school_list)]

print(word_list)

到目前为止的结果:

[((0, 'ABC'), (0, 'BOARDING')), ((1, 'UNIVERSITY'), (1, 'INSTITUTE')), ((2, 'MARIE'), (2, 'SCHOOL')), ((3, 'RALPH'), (3, 'DISTRICT')), ((4, 'UNIVERSAL'), (4, 'ADMINISTRATION'))]

您现在有一个配对列表,每所学校一对。你可以展平这个列表——或者你真正需要的任何其他组织——然后制作一个数据框。

如果它对您更有效,也许将前最后部分放入生成器中,这样您只构建一个50 万条记录的项目。

于 2019-12-12T19:17:57.367 回答