为预测集群创建一个新列:SettingWithCopyWarning

Posted

技术标签:

【中文标题】为预测集群创建一个新列:SettingWithCopyWarning【英文标题】:Creating a new column for predicted cluster: SettingWithCopyWarning 【发布时间】:2020-09-07 11:25:15 【问题描述】:

不幸的是,这个问题将重复,但我无法在我的代码中解决这个问题,即使在查看了其他类似问题及其相关答案之后也是如此。 我需要将我的数据集拆分为训练一个测试数据集。但是,当我添加一个新列来预测集群时,我似乎犯了一些错误。 我得到的错误是:

/anaconda3/lib/python3.7/site-packages/ipykernel_launcher.py:3: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  This is separate from the ipykernel package so we can avoid doing imports until

关于这个错误有几个问题,但可能我做错了什么,因为我还没有解决这个问题,我仍然遇到与上面相同的错误。 数据集如下:

    Date    Link    Value   
0   03/15/2020  https://www.bbc.com 1
1   03/15/2020  https://www.netflix.com 4   
2   03/15/2020  https://www.google.com 10
...

我已将数据集拆分为训练集和测试集,如下所示:

import sklearn
from sklearn.model_selection import cross_validate
from sklearn.model_selection import train_test_split
import re
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.cluster import KMeans
from nltk.tokenize import word_tokenize
from nltk.stem import WordNetLemmatizer
import nltk
import string as st 

train_data=df.Link.tolist()
df_train=pd.DataFrame(train_data, columns = ['Review'])
X = df_train

X_train, X_test = train_test_split(
        X, test_size=0.4).copy()
X_test, X_val = train_test_split(
        X_test, test_size=0.5).copy()
print(X_train.isna().sum())
print(X_test.isna().sum())

stop_words = stopwords.words('english')

def preprocessor(t):
    t = re.sub(r"[^a-zA-Z]", " ", t())
    words = word_tokenize(t)
    w_lemm = [WordNetLemmatizer().lemmatize(w) for w in words if w not in stop_words]
    return w_lemm


vect =TfidfVectorizer(tokenizer= preprocessor)
vectorized_text=vect.fit_transform(X_train['Review'])
kmeans =KMeans(n_clusters=3).fit(vectorized_text)

导致错误的代码行是:

cl=kmeans.predict(vectorized_text)
X_train['Cluster']=pd.Series(cl, index=X_train.index)

我认为这两个问题应该可以帮助我编写代码:

How to add k-means predicted clusters in a column to a dataframe in Python

How to deal with SettingWithCopyWarning in Pandas?

但我的代码中仍然存在一些问题。

您能否先看看它并帮我解决这个问题,然后再将这个问题作为重复而关闭?

【问题讨论】:

请在删除已关闭为重复的问题并逐字重新打开之前,请确保显示链接的答案无法解决您的问题,而不仅仅是说“但有些东西在我的代码中仍然是错误的”;第一个答案清楚地显示了如何将给你错误的行分成两个步骤,即cl=kmeans.predict(vectorized_text),然后是X_train['Cluster']=pd.Series(cl, index=X_train.index)。你真的尝试过吗?如果是,但仍然出现错误,请在此处相应地修改您显示的代码。 第一个答案确实有问题(应该是pd.Series而不是Series);请使用那里的(编辑的)答案检查并确认您的问题已得到解决。 好的,那么,正如我所说,请修改您的代码以显示这一点(从而证明您的问题不是重复的)。 这不是错误,而是警告。您是否访问了警告中建议的链接?每当您将数据分配给数据帧切片的副本时,您都会收到此消息。这不一定是代码中的错误,这就是为什么它是警告而不是错误的原因。 是的,我做到了,但我不明白我应该怎么做才能让它消失/修复它 【参考方案1】:

恕我直言,train_test_split 为您提供了一个元组,当您执行 copy() 时,copy()tuple 的操作,而不是 pandas 的操作。这会触发 pandas 臭名昭著的复制警告。

所以你只创建元组的浅拷贝,而不是元素。换句话说

X_train, X_test = train_test_split(X, test_size=0.4).copy()

相当于:

train_test = train_test_split(X, test_size=0.4)
train_test_copy = train_test.copy()
X_train, X_test = train_test_copy[0], train_test_copy[1]

由于 pandas 数据帧是指针,X_trainX_test 可能指向也可能不指向与 X 相同的数据。如果要复制数据帧,则应在每个数据帧上显式强制copy()

X_train, X_test = train_test_split(X, test_size=0.4)
X_train, X_test = X_train.copy(), X_test.copy()

X_train, X_test = [d.copy() for d in train_test_split(X, test_size=0.4)]

那么每个X_trainX_test 都是一个指向新内存数据的新数据帧。


更新:测试此代码没有任何警告:

X = pd.DataFrame(np.random.rand(100,3))
X_train, X_test = train_test_split(X, test_size=0.4)
X_train, X_test = X_train.copy(), X_test.copy()

X_train['abcd'] = 1

【讨论】:

非常感谢@Quang Hoang。它修复了警告。

以上是关于为预测集群创建一个新列:SettingWithCopyWarning的主要内容,如果未能解决你的问题,请参考以下文章

使用经过训练的 K-Means 模型为未见数据预测正确的集群

Pandas Dataframe to pivot table - 根据前两列的添加创建新列

将随机森林预测作为列添加到测试文件中

预测最近的集群 sklearn

预测 R 之外的 mclust 集群成员资格

为多索引 Panda 数据框创建基于另一列的新列