如何将含多类型数据的Pandas DataFrame转换为向量DataFrame?
问题描述
我有一个超过1000行的Pandas DataFrame,包含数值、对象、字符串和布尔值类型的数据。我想把DataFrame的每个单元格转换成向量,之后基于这些向量比较每行的相似性。
示例数据
Col 0,Col 1,Col 2,Col 3,Col 4,Col 5,Col 6,Col 7,Col 8,Col 9,Col 10 12,65e1e35b7fe333,harry Joe,1,FALSE,swe,1,142.158.0.2,10.10.0.2,text1,0 13,65e1e35b7fe599,allen,1,FALSE,swe,1,142.158.0.20,10.10.0.20,text2,0 14,65e1e35b7fe165,carter,1,FALSE,swe,1,142.158.0.21,10.10.0.21,text3,0
期望结果
希望得到每个单元格对应向量的DataFrame(示例用VectX表示向量):
Col 0,Col 1,Col 2,Col 3,Col 4,Col 5,Col 6,Col 7,Col 8,Col 9,Col 10 Vect1,Vect2,Vect3,Vect4,Vect5,Vect6,Vect7,Vect8,Vect9,Vect10,Vect11 Vect12,Vect13,Vect14,Vect4,Vect5,Vect6,Vect7,Vect15,Vect16,Vect17,Vect11 Vect18,Vect19,Vect20,Vect4,Vect5,Vect6,Vect7,Vect21,Vect22,Vect23,Vect11
尝试的代码及报错
我尝试用Scikit-learn的TfidfVectorizer实现,但报错了:
import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer df = mydata vectorizer = TfidfVectorizer() # 转换数据为特征向量 X = vectorizer.fit_transform(df) X = pd.DataFrame(_X.todense(), index=df.index, columns=vectorizer.vocabulary_) X.head() # 标签 y = df['label']
报错信息:
TypeError Traceback (most recent call last) Cell In[11], line 14 11 vectorizer = TfidfVectorizer() 13 # Transform the text data to feature vectors ---> 14 X = vectorizer.fit_transform(df) 16 X = pd.DataFrame(_X.todense(), index=df.index, columns=vectorizer.vocabulary_) 17 X.head() File /anaconda/envs/xxx_py38/lib/python3.9/site-packages/sklearn/feature_extraction/text.py:2079, in TfidfVectorizer.fit_transform(self, raw_documents, y) 2072 self._check_params() 2073 self._tfidf = TfidfTransformer( 2074 norm=self.norm, 2075 use_idf=self.use_idf, 2076 smooth_idf=self.smooth_idf, 2077 sublinear_tf=self.sublinear_tf, 2078 ) -> 2079 X = super().fit_transform(raw_documents) 2080 self._tfidf.fit(X) 2081 # X is already a transformed view of raw_documents so 2082 # we set copy to False File /anaconda/envs/xxx_py38/lib/python3.9/site-packages/sklearn/feature_extraction/text.py:1338, in CountVectorizer.fit_transform(self, raw_documents, y) 1330 warnings.warn( 1331 "Upper case characters found in" 1332 " vocabulary while 'lowercase'" 1333 " is True. These entries will not" 1334 " be matched with any documents" 1335 ) 1336 break -> 1338 vocabulary, X = self._count_vocab(raw_documents, self.fixed_vocabulary_) 1340 if self.binary: 1341 X.data.fill(1) File /anaconda/envs/xxx_py38/lib/python3.9/site-packages/sklearn/feature_extraction/text.py:1207, in CountVectorizer._count_vocab(self, raw_documents, fixed_vocab) 1205 values = _make_int_array() 1206 indptr.append(0) -> 1207 for doc in raw_documents: 1208 feature_counter = {} 1209 for feature in analyze(doc): TypeError: 'Data' object is not iterable
解决方案
报错原因
你直接把整个DataFrame传给TfidfVectorizer.fit_transform(),但这个方法只接受文本序列(比如字符串列表、单列文本Series),无法处理多列混合类型的DataFrame,因此抛出了'Data' object is not iterable的错误。
实现步骤
要实现每个单元格转向量并计算行相似性,需针对不同类型的列分别处理,再合并所有列的向量表示,最终得到每行的完整向量用于相似性计算:
- 区分列类型:将DataFrame的列分为数值型(含布尔值)、字符串/对象型两类。
- 分别向量化:数值/布尔列可直接保留数值或标准化;字符串/对象列用TF-IDF或词频统计转向量,结构化字符串(如IP)可拆分后转数值。
- 合并向量:将各列的向量结果拼接,得到每行的完整特征向量。
- 计算相似性:用余弦相似度或成对距离计算行之间的相似性。
示例代码
import pandas as pd from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.preprocessing import StandardScaler from sklearn.metrics.pairwise import cosine_similarity # 加载示例数据 data = """Col 0,Col 1,Col 2,Col 3,Col 4,Col 5,Col 6,Col 7,Col 8,Col 9,Col 10 12,65e1e35b7fe333,harry Joe,1,FALSE,swe,1,142.158.0.2,10.10.0.2,text1,0 13,65e1e35b7fe599,allen,1,FALSE,swe,1,142.158.0.20,10.10.0.20,text2,0 14,65e1e35b7fe165,carter,1,FALSE,swe,1,142.158.0.21,10.10.0.21,text3,0""" df = pd.read_csv(pd.io.common.StringIO(data)) # 1. 处理数值/布尔列 numeric_cols = df.select_dtypes(include=['int64', 'float64', 'bool']).columns scaler = StandardScaler() numeric_vecs = scaler.fit_transform(df[numeric_cols]) numeric_df = pd.DataFrame(numeric_vecs, columns=[f"{col}_vec" for col in numeric_cols], index=df.index) # 2. 处理字符串/对象列 text_cols = df.select_dtypes(include=['object']).columns text_vec_list = [] for col in text_cols: vectorizer = TfidfVectorizer() col_vecs = vectorizer.fit_transform(df[col].astype(str)) col_df = pd.DataFrame(col_vecs.todense(), columns=[f"{col}_vec_{word}" for word in vectorizer.get_feature_names_out()], index=df.index) text_vec_list.append(col_df) text_df = pd.concat(text_vec_list, axis=1) # 3. 合并所有向量,得到每行完整特征向量 full_vec_df = pd.concat([numeric_df, text_df], axis=1) # 4. 计算行余弦相似性 similarity_matrix = cosine_similarity(full_vec_df) similarity_df = pd.DataFrame(similarity_matrix, index=df.index, columns=df.index) print("每行完整特征向量:") print(full_vec_df.head()) print("\n行相似性矩阵:") print(similarity_df)
单元格单独存向量的实现
如果希望每个单元格单独存储向量(而非合并成大向量),可参考以下代码:
vec_df = df.copy() # 处理文本列,每个单元格存TF-IDF向量 text_cols = df.select_dtypes(include=['object']).columns for col in text_cols: vectorizer = TfidfVectorizer() vecs = vectorizer.fit_transform(df[col].astype(str)) vec_df[col] = [row.toarray().flatten() for row in vecs] # 处理数值/布尔列,转为单元素向量 numeric_cols = df.select_dtypes(include=['int64', 'float64', 'bool']).columns for col in numeric_cols: vec_df[col] = df[col].apply(lambda x: [x]) print("每个单元格为向量的DataFrame:") print(vec_df)
内容的提问来源于stack exchange,提问作者Tavi
相关产品推荐
相关产品推荐

