【问题标题】:Constructing pandas DataFrame from values in variables gives "ValueError: If using all scalar values, you must pass an index"从变量中的值构造 pandas DataFrame 会给出“ValueError:如果使用所有标量值,则必须传递一个索引”
【发布时间】:2013-07-24 06:44:30
【问题描述】:

这可能是一个简单的问题,但我不知道该怎么做。假设我有两个变量如下。

a = 2
b = 3

我想由此构造一个 DataFrame:

df2 = pd.DataFrame({'A':a,'B':b})

这会产生一个错误:

ValueError: 如果使用所有标量值,则必须传递索引

我也试过这个:

df2 = (pd.DataFrame({'a':a,'b':b})).reset_index()

这给出了相同的错误消息。

【问题讨论】:

  • 我错过了什么吗?由于在评估 DataFrame 构造函数时会产生异常,所以没有 .foo() 会解决错误,这不是很简单吗?

标签: python pandas dataframe scalar


【解决方案1】:

错误消息表明,如果您要传递标量值,则必须传递一个索引。因此,您不能对列使用标量值 - 例如使用列表:

>>> df = pd.DataFrame({'A': [a], 'B': [b]})
>>> df
   A  B
0  2  3

或使用标量值并传递索引:

>>> df = pd.DataFrame({'A': a, 'B': b}, index=[0])
>>> df
   A  B
0  2  3

【讨论】:

  • 可能是因为 Python 中列表中的项目顺序是持久的,而字典中的项目顺序不是。您可以使用空字典实例化 DataFrame。原则上,我认为此处显示的单行 DataFrame 也可以从字典构建,因为顺序无关紧要(但这尚未实现)。但是对于多行,Pandas 将无法创建 DataFrame,因为它不知道哪些项目属于同一行。
  • @VitalyIsaev - 在这种情况下,数据帧行(由给定字典表示)没有索引(甚至没有隐式索引)。一个简单的解决方案是将字典包装在一个列表中,该列表确实具有“自然索引”。可以声称如果只给出一个字典(没有包装列表),那么假设index=0,但这可能导致意外误用(认为单个字典可以以某种方式创建多行数据框)
  • 此链接中的几种解决方案eulertech.wordpress.com/2017/11/28/…
  • 这样做的原因是因为 DataFrames 旨在保存二维数据(即 OP 的两个变量的行)。如果您只想保存索引-> 值对(如字典),那么您应该使用系列,正如Rob 建议的那样。
  • 这是单个样本/行数据框,因此 index = [0] 合乎逻辑;但您也可以将其设置为 index=[100],这样就可以了。问:Index 不应该按逻辑递增排序吗,为什么 python 允许 Index 操作?
【解决方案2】:

你也可以使用pd.DataFrame.from_records,当你已经有字典的时候更方便:

df = pd.DataFrame.from_records([{ 'A':a,'B':b }])

如果需要,您还可以通过以下方式设置索引:

df = pd.DataFrame.from_records([{ 'A':a,'B':b }], index='A')

【讨论】:

  • @DaveKielpinski 请检查您是否将 list 传递给“from_records”方法;否则它将不起作用,并且您将收到与在字典上调用 DataFrame 时相同的错误消息。
  • 与@DaveKielpinski 相同的问题,直到我意识到我在单个文档上使用from_records,而不是在这样的数组上。只是发布这个以防它提醒你仔细检查你是否做对了。
  • @mingchau:这是标准行为,因此与手头的问题无关。
【解决方案3】:

您可以尝试将您的字典包装成一个列表:

my_dict = {'A':1,'B':2}
pd.DataFrame([my_dict])
   A  B
0  1  2

【讨论】:

  • 它也适用于具有多种数据类型的大型字典,只需将字典放在括号中 [ ] 正如你提到的@NewBie。接受的答案不是那么快,因为需要对所有标量值执行此操作,谢谢!
【解决方案4】:

您需要先创建一个熊猫系列。第二步是将pandas系列转换为pandas dataframe。

import pandas as pd
data = {'a': 1, 'b': 2}
pd.Series(data).to_frame()

您甚至可以提供列名。

pd.Series(data).to_frame('ColumnName')

【讨论】:

  • 这对我有用。我的字典有整数键和 ndarray 值。
  • pd.Series(data).to_frame('ColumnName') 更短,虽然这个等价物可能更直接:pd.DataFrame.from_dict(data, orient='index', columns=['ColumnName'])
  • 这对我也有用,与@StatsSorceress 相同。
【解决方案5】:

也许 Series 会提供您需要的所有功能:

pd.Series({'A':a,'B':b})

DataFrame 可以被认为是 Series 的集合,因此您可以:

  • 将多个系列连接成一个数据帧(如here 所述)

  • 将 Series 变量添加到现有数据框 (example here)

【讨论】:

    【解决方案6】:

    我在使用 numpy 数组时遇到了同样的问题,解决方案是将它们展平:

    data = {
        'b': array1.flatten(),
        'a': array2.flatten(),
    }
    
    df = pd.DataFrame(data)
    

    【讨论】:

      【解决方案7】:

      熊猫的魔法在起作用。所有的逻辑都出来了。

      错误信息"ValueError: If using all scalar values, you must pass an index" 说你必须传递一个索引。

      这并不一定意味着传递索引会让 pandas 做你想让它做的事情

      当您传递索引时,pandas 会将您的字典键视为列名,并将值视为该列应包含索引中每个值的内容。

      a = 2
      b = 3
      df2 = pd.DataFrame({'A':a,'B':b}, index=[1])
      
          A   B
      1   2   3
      

      传递更大的索引:

      df2 = pd.DataFrame({'A':a,'B':b}, index=[1, 2, 3, 4])
      
          A   B
      1   2   3
      2   2   3
      3   2   3
      4   2   3
      

      当没有给出索引时,通常由数据框自动生成索引。但是,pandas 不知道你想要多少行23。但是,您可以更明确地说明它

      df2 = pd.DataFrame({'A':[a]*4,'B':[b]*4})
      df2
      
          A   B
      0   2   3
      1   2   3
      2   2   3
      3   2   3
      

      默认索引是基于 0 的。

      我建议在创建数据框时始终将列表字典传递给数据框构造函数。其他开发人员更容易阅读。 Pandas 有很多警告,不要让其他开发人员必须成为所有这些方面的专家才能阅读您的代码。

      【讨论】:

        【解决方案8】:

        您需要提供可迭代作为 Pandas DataFrame 列的值:

        df2 = pd.DataFrame({'A':[a],'B':[b]})
        

        【讨论】:

          【解决方案9】:

          你可以试试:

          df2 = pd.DataFrame.from_dict({'a':a,'b':b}, orient = 'index')
          

          来自“orient”参数的文档:如果传递的 dict 的键应该是结果 DataFrame 的列,则传递“columns”(默认)。否则,如果键应该是行,则传递“索引”。

          【讨论】:

          • 这并不能解决所提出的问题,它会产生与预期不同的结果。
          【解决方案10】:

          我通常使用以下方法从dicts快速创建一个小表。

          假设您有一个字典,其中键是文件名,值是它们对应的文件大小,您可以使用以下代码将其放入 DataFrame 中(注意字典上的 .items() 调用):

          files = {'A.txt':12, 'B.txt':34, 'C.txt':56, 'D.txt':78}
          filesFrame = pd.DataFrame(files.items(), columns=['filename','size'])
          print(filesFrame)
          
            filename  size
          0    A.txt    12
          1    B.txt    34
          2    C.txt    56
          3    D.txt    78
          

          【讨论】:

          • 这很有帮助,但请注意它不适用于 pandas 0.23.4
          • 对我来说这是完美的!在字典中仅包含两行数据并将其转换为数据框应该不难。
          【解决方案11】:

          我尝试了 transpose() 并且成功了。 缺点:您创建了一个新对象。

          testdict1 = {'key1':'val1','key2':'val2','key3':'val3','key4':'val4'}
          
          df = pd.DataFrame.from_dict(data=testdict1,orient='index')
          print(df)
          print(f'ID for DataFrame before Transpose: {id(df)}\n')
          
          df = df.transpose()
          print(df)
          print(f'ID for DataFrame after Transpose: {id(df)}')
          

          输出

                   0
          key1  val1
          key2  val2
          key3  val3
          key4  val4
          ID for DataFrame before Transpose: 1932797100424
          
             key1  key2  key3  key4
          0  val1  val2  val3  val4
          ID for DataFrame after Transpose: 1932797125448
          
          ​```
          

          【讨论】:

            【解决方案12】:

            如果您打算转换标量字典,则必须包含索引:

            import pandas as pd
            
            alphabets = {'A': 'a', 'B': 'b'}
            index = [0]
            alphabets_df = pd.DataFrame(alphabets, index=index)
            print(alphabets_df)
            

            虽然列表字典不需要索引,但同样的想法可以扩展到列表字典:

            planets = {'planet': ['earth', 'mars', 'jupiter'], 'length_of_day': ['1', '1.03', '0.414']}
            index = [0, 1, 2]
            planets_df = pd.DataFrame(planets, index=index)
            print(planets_df)
            

            当然,对于列表字典,您可以构建不带索引的数据框:

            planets_df = pd.DataFrame(planets)
            print(planets_df)
            

            【讨论】:

              【解决方案13】:

              输入不必是记录列表 - 它也可以是单个字典:

              pd.DataFrame.from_records({'a':1,'b':2}, index=[0])
                 a  b
              0  1  2
              

              这似乎相当于:

              pd.DataFrame({'a':1,'b':2}, index=[0])
                 a  b
              0  1  2
              

              【讨论】:

                【解决方案14】:

                这是因为 DataFrame 有两个直观的维度 - 列 行。

                您只是使用字典键指定列。

                如果您只想指定一维数据,请使用系列!

                【讨论】:

                  【解决方案15】:

                  最简单的选项 ls :

                  dict  = {'A':a,'B':b}
                  df = pd.DataFrame(dict, index = np.arange(1) )
                  

                  【讨论】:

                    【解决方案16】:

                    另一种选择是使用字典理解将标量动态转换为列表:

                    df = pd.DataFrame(data={k: [v] for k, v in mydict.items()})
                    

                    表达式 {...} 创建一个新的字典,其值是一个包含 1 个元素的列表。如:

                    In [20]: mydict
                    Out[20]: {'a': 1, 'b': 2}
                    
                    In [21]: mydict2 = { k: [v] for k, v in mydict.items()}
                    
                    In [22]: mydict2
                    Out[22]: {'a': [1], 'b': [2]}
                    

                    【讨论】:

                      【解决方案17】:

                      将字典转换为数据框

                      col_dict_df = pd.Series(col_dict).to_frame('new_col').reset_index()
                      

                      为列命名

                      col_dict_df.columns = ['col1', 'col2']
                      

                      【讨论】:

                        【解决方案18】:

                        将“a”和“b”值更改为列表,如下所示:

                        a = [2]
                        b = [3]
                        

                        然后执行相同的代码如下:

                        df2 = pd.DataFrame({'A':a,'B':b})
                        df2
                        

                        你会得到:

                            A   B
                        0   2   3
                        

                        【讨论】:

                          【解决方案19】:
                          import pandas as pd
                           a=2
                           b=3
                          dict = {'A': a, 'B': b}
                          
                          pd.DataFrame(pd.Series(dict)).T  
                          # *T :transforms the dataframe*
                          
                             Result:
                              A   B
                          0   2   3
                          

                          【讨论】:

                          • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
                          • 您的回答将.T 添加到其他答案的建议中。你能解释一下这有什么不同吗?
                          • 这个问题有 21 个现有答案,包括一个接受了 836 个赞成的答案 (!!!)。您确定尚未提供您的答案吗?如果不是,为什么有人会更喜欢您的方法而不是提议的现有方法?您是否正在利用新功能?是否存在更适合您的方法的场景?解释总是有用,但在这里尤其很重要。
                          【解决方案20】:

                          你可以试试这个: df2 = pd.DataFrame.from_dict({'a':a,'b':b}, orient = 'index')

                          【讨论】:

                          • 这与@MathewConnell 发布的答案完全相同,但没有格式化...
                          【解决方案21】:

                          如果你有字典,你可以用下面这行代码把它变成熊猫数据框:

                          pd.DataFrame({"key": d.keys(), "value": d.values()})
                          

                          【讨论】:

                          • 它有效,但恕我直言,它没有多大意义 ` <!-- language: lang-py --> fruits_count = defaultdict(int) fruits_count["apples"] = 10 fruits_count["bananas"] = 21 pd.DataFrame({"key" : fruits_count.keys(), "value" : fruits_count.values()}) 输出:键值 0(香蕉、苹果)(21, 10) 1 (香蕉、苹果) (21, 10)
                          【解决方案22】:

                          只需在列表中传递 dict:

                          a = 2
                          b = 3
                          df2 = pd.DataFrame([{'A':a,'B':b}])
                          

                          【讨论】:

                            猜你喜欢
                            • 2017-02-19
                            • 2016-11-17
                            • 2021-06-01
                            • 1970-01-01
                            • 2018-05-29
                            • 2021-07-14
                            相关资源
                            最近更新 更多