<h3 dir="auto">Describe the bug</h3>
<div class="highlight highlight-text-python-traceback notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="[sklearn/feature_extraction/text.py]n _preprocess(doc, accent_function, lower)
     69     &quot;&quot;&quot;
     70     if lower:
---&gt; 71         doc = doc.lower()
     72     if accent_function is not None:
     73         doc = accent_function(doc)

AttributeError: 'list' object has no attribute 'lower'"><pre class="notranslate">[sklearn/feature_extraction/text.py]n _preprocess(doc, accent_function, lower)
     <span class="pl-c1">69</span>     <span class="pl-s"><span class="pl-pds">"""</span></span>
     <span class="pl-c1">70</span>     <span class="pl-k">if</span> lower:
---&gt; 71         doc = doc.lower()
     <span class="pl-c1">72</span>     <span class="pl-k">if</span> accent_function <span class="pl-k">is</span> <span class="pl-k">not</span> <span class="pl-c1">None</span>:
     <span class="pl-c1">73</span>         doc <span class="pl-k">=</span> accent_function(doc)

<span class="pl-en">AttributeError</span>: <span class="pl-s">'list' object has no attribute 'lower'</span></pre></div>
<h3 dir="auto">Steps/Code to Reproduce</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="def cosine_similarity_T(k, query):
  print(&quot;1&quot;)
  preprocessed_query = re.sub(&quot;\W+&quot;, &quot; &quot;, query).strip()
  print(&quot;2&quot;)
  tokens = word_tokenize(str(preprocessed_query))
  q_df = pd.DataFrame(columns=['q_clean'])
  q_df.loc[0,'q_clean'] =tokens
  q_df['q_clean'] =q_df['q_clean'].apply(lambda x: remove_stopwords(x))
  d_cosines = []
  print(&quot;3&quot;)
  query_vector = gen_vector_T(q_df['q_clean'])
  
    
  for d in vectors.A:
    d_cosines.append(cosine_sim(query_vector, d))
                    
  out = np.array(d_cosines).argsort()[-k:][::-1]
    #print(&quot;&quot;)
  d_cosines.sort()
  a = pd.DataFrame()
  for i,index in enumerate(out):
    a.loc[i,'index'] = str(index)
    a.loc[i,'Subject'] = df['Subject'][index]
  for j,simScore in enumerate(d_cosines[-k:][::-1]):
    a.loc[j,'Score'] = simScore
  return "><pre class="notranslate"><span class="pl-k">def</span> <span class="pl-en">cosine_similarity_T</span>(<span class="pl-s1">k</span>, <span class="pl-s1">query</span>):
  <span class="pl-en">print</span>(<span class="pl-s">"1"</span>)
  <span class="pl-s1">preprocessed_query</span> <span class="pl-c1">=</span> <span class="pl-s1">re</span>.<span class="pl-en">sub</span>(<span class="pl-s">"\W+"</span>, <span class="pl-s">" "</span>, <span class="pl-s1">query</span>).<span class="pl-en">strip</span>()
  <span class="pl-en">print</span>(<span class="pl-s">"2"</span>)
  <span class="pl-s1">tokens</span> <span class="pl-c1">=</span> <span class="pl-en">word_tokenize</span>(<span class="pl-en">str</span>(<span class="pl-s1">preprocessed_query</span>))
  <span class="pl-s1">q_df</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>(<span class="pl-s1">columns</span><span class="pl-c1">=</span>[<span class="pl-s">'q_clean'</span>])
  <span class="pl-s1">q_df</span>.<span class="pl-s1">loc</span>[<span class="pl-c1">0</span>,<span class="pl-s">'q_clean'</span>] <span class="pl-c1">=</span><span class="pl-s1">tokens</span>
  <span class="pl-s1">q_df</span>[<span class="pl-s">'q_clean'</span>] <span class="pl-c1">=</span><span class="pl-s1">q_df</span>[<span class="pl-s">'q_clean'</span>].<span class="pl-en">apply</span>(<span class="pl-k">lambda</span> <span class="pl-s1">x</span>: <span class="pl-en">remove_stopwords</span>(<span class="pl-s1">x</span>))
  <span class="pl-s1">d_cosines</span> <span class="pl-c1">=</span> []
  <span class="pl-en">print</span>(<span class="pl-s">"3"</span>)
  <span class="pl-s1">query_vector</span> <span class="pl-c1">=</span> <span class="pl-en">gen_vector_T</span>(<span class="pl-s1">q_df</span>[<span class="pl-s">'q_clean'</span>])
  
    
  <span class="pl-k">for</span> <span class="pl-s1">d</span> <span class="pl-c1">in</span> <span class="pl-s1">vectors</span>.<span class="pl-v">A</span>:
    <span class="pl-s1">d_cosines</span>.<span class="pl-en">append</span>(<span class="pl-en">cosine_sim</span>(<span class="pl-s1">query_vector</span>, <span class="pl-s1">d</span>))
                    
  <span class="pl-s1">out</span> <span class="pl-c1">=</span> <span class="pl-s1">np</span>.<span class="pl-en">array</span>(<span class="pl-s1">d_cosines</span>).<span class="pl-en">argsort</span>()[<span class="pl-c1">-</span><span class="pl-s1">k</span>:][::<span class="pl-c1">-</span><span class="pl-c1">1</span>]
    <span class="pl-c">#print("")</span>
  <span class="pl-s1">d_cosines</span>.<span class="pl-en">sort</span>()
  <span class="pl-s1">a</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>()
  <span class="pl-k">for</span> <span class="pl-s1">i</span>,<span class="pl-s1">index</span> <span class="pl-c1">in</span> <span class="pl-en">enumerate</span>(<span class="pl-s1">out</span>):
    <span class="pl-s1">a</span>.<span class="pl-s1">loc</span>[<span class="pl-s1">i</span>,<span class="pl-s">'index'</span>] <span class="pl-c1">=</span> <span class="pl-en">str</span>(<span class="pl-s1">index</span>)
    <span class="pl-s1">a</span>.<span class="pl-s1">loc</span>[<span class="pl-s1">i</span>,<span class="pl-s">'Subject'</span>] <span class="pl-c1">=</span> <span class="pl-s1">df</span>[<span class="pl-s">'Subject'</span>][<span class="pl-s1">index</span>]
  <span class="pl-k">for</span> <span class="pl-s1">j</span>,<span class="pl-s1">simScore</span> <span class="pl-c1">in</span> <span class="pl-en">enumerate</span>(<span class="pl-s1">d_cosines</span>[<span class="pl-c1">-</span><span class="pl-s1">k</span>:][::<span class="pl-c1">-</span><span class="pl-c1">1</span>]):
    <span class="pl-s1">a</span>.<span class="pl-s1">loc</span>[<span class="pl-s1">j</span>,<span class="pl-s">'Score'</span>] <span class="pl-c1">=</span> <span class="pl-s1">simScore</span>
  <span class="pl-k">return</span> </pre></div>
<h3 dir="auto">Expected Results</h3>
<p dir="auto">ist gets converted to lowercase as well</p>
<h3 dir="auto">Actual Results</h3>
<p dir="auto">only string gets converted to lowecase</p>
<h3 dir="auto">Versions</h3>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="wish we could have that functionality to convert a list to lowercase too as we do for a string"><pre class="notranslate">wish we could have that functionality to convert a list to lowercase too as we <span class="pl-k">do</span> <span class="pl-k">for</span> a string</pre></div>
<p dir="auto">I wonder if we should allow <code class="notranslate">(n_samples, 1)</code> input to CountVectorizer. I think we had this discussion before, right now we basically have a special case in <code class="notranslate">ColumnTransformer</code> with scalar columns to produce 1d arrays.<br>
Does anyone remember where this discussion was?</p>
<p dir="auto">A lot of my students are struggling with putting a CountVectorizer into a ColumnTransformer and it might be nice to be more generous with the input formats, and ensure we raise nice error messages.</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
X = pd.DataFrame([&quot;what is my purpose?&quot;, &quot;You bring the butter.&quot;])
CountVectorizer().fit_transform(X)"><pre class="notranslate"><span class="pl-k">import</span> <span class="pl-s1">pandas</span> <span class="pl-k">as</span> <span class="pl-s1">pd</span>
<span class="pl-k">from</span> <span class="pl-s1">sklearn</span>.<span class="pl-s1">feature_extraction</span>.<span class="pl-s1">text</span> <span class="pl-k">import</span> <span class="pl-v">CountVectorizer</span>
<span class="pl-v">X</span> <span class="pl-c1">=</span> <span class="pl-s1">pd</span>.<span class="pl-v">DataFrame</span>([<span class="pl-s">"what is my purpose?"</span>, <span class="pl-s">"You bring the butter."</span>])
<span class="pl-v">CountVectorizer</span>().<span class="pl-en">fit_transform</span>(<span class="pl-v">X</span>)</pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
&lt;ipython-input-6-6cae33e8c706&gt; in &lt;module&gt;
      3 from sklearn.compose import ColumnTransformer
      4 X = pd.DataFrame([&quot;what is my purpose?&quot;, &quot;You bring the butter.&quot;])
----&gt; 5 CountVectorizer().fit_transform(X)

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in fit_transform(self, raw_documents, y)
   1218 
   1219         vocabulary, X = self._count_vocab(raw_documents,
-&gt; 1220                                           self.fixed_vocabulary_)
   1221 
   1222         if self.binary:

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in _count_vocab(self, raw_documents, fixed_vocab)
   1129         for doc in raw_documents:
   1130             feature_counter = {}
-&gt; 1131             for feature in analyze(doc):
   1132                 try:
   1133                     feature_idx = vocabulary[feature]

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in _analyze(doc, analyzer, tokenizer, ngrams, preprocessor, decoder, stop_words)
    101     else:
    102         if preprocessor is not None:
--&gt; 103             doc = preprocessor(doc)
    104         if tokenizer is not None:
    105             doc = tokenizer(doc)

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in _preprocess(doc, accent_function, lower)
     66     &quot;&quot;&quot;
     67     if lower:
---&gt; 68         doc = doc.lower()
     69     if accent_function is not None:
     70         doc = accent_function(doc)

AttributeError: 'int' object has no attribute 'lower'"><pre lang="pythontb" class="notranslate"><code class="notranslate">---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
&lt;ipython-input-6-6cae33e8c706&gt; in &lt;module&gt;
      3 from sklearn.compose import ColumnTransformer
      4 X = pd.DataFrame(["what is my purpose?", "You bring the butter."])
----&gt; 5 CountVectorizer().fit_transform(X)

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in fit_transform(self, raw_documents, y)
   1218 
   1219         vocabulary, X = self._count_vocab(raw_documents,
-&gt; 1220                                           self.fixed_vocabulary_)
   1221 
   1222         if self.binary:

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in _count_vocab(self, raw_documents, fixed_vocab)
   1129         for doc in raw_documents:
   1130             feature_counter = {}
-&gt; 1131             for feature in analyze(doc):
   1132                 try:
   1133                     feature_idx = vocabulary[feature]

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in _analyze(doc, analyzer, tokenizer, ngrams, preprocessor, decoder, stop_words)
    101     else:
    102         if preprocessor is not None:
--&gt; 103             doc = preprocessor(doc)
    104         if tokenizer is not None:
    105             doc = tokenizer(doc)

~/miniconda3/lib/python3.7/site-packages/sklearn/feature_extraction/text.py in _preprocess(doc, accent_function, lower)
     66     """
     67     if lower:
---&gt; 68         doc = doc.lower()
     69     if accent_function is not None:
     70         doc = accent_function(doc)

AttributeError: 'int' object has no attribute 'lower'
</code></pre></div>