【问题标题】:Pretty printing newlines inside a string in a Pandas DataFrame在 Pandas DataFrame 中的字符串内漂亮地打印换行符
【发布时间】:2016-03-23 04:54:53
【问题描述】:

我有一个 Pandas DataFrame,其中一列包含字符串元素,而这些字符串元素包含我想逐字打印的新行。但它们只是在输出中显示为\n

也就是说,我要打印这个:

  pos     bidder
0   1
1   2
2   3  <- alice
       <- bob
3   4

但这就是我得到的:

  pos            bidder
0   1
1   2
2   3  <- alice\n<- bob
3   4

我怎样才能完成我想要的?我可以使用 DataFrame,还是必须恢复为一次手动打印一行填充的列?

这是我目前所拥有的:

n = 4
output = pd.DataFrame({
    'pos': range(1, n+1),
    'bidder': [''] * n
})
bids = {'alice': 3, 'bob': 3}
used_pos = []
for bidder, pos in bids.items():
    if pos in used_pos:
        arrow = output.ix[pos, 'bidder']
        output.ix[pos, 'bidder'] = arrow + "\n<- %s" % bidder
    else:
        output.ix[pos, 'bidder'] = "<- %s" % bidder
print(output)

【问题讨论】:

    标签: python string python-3.x pandas printing


    【解决方案1】:

    使用 pandas .set_properties() 和 CSS white-space 属性

    [用于 IPython 笔记本]

    另一种方法是使用 pandas 的 pandas.io.formats.style.Styler.set_properties() 方法和 CSS "white-space": "pre-wrap" 属性:

    from IPython.display import display
    
    # Assuming the variable df contains the relevant DataFrame
    display(df.style.set_properties(**{
        'white-space': 'pre-wrap',
    })
    
    

    要保持文本左对齐,您可能需要添加'text-align': 'left',如下所示:

    from IPython.display import display
    
    # Assuming the variable df contains the relevant DataFrame
    display(df.style.set_properties(**{
        'text-align': 'left',
        'white-space': 'pre-wrap',
    })
    
    

    【讨论】:

      【解决方案2】:

      有点符合 unsorted 的回答:

      import pandas as pd
      
      # Save the original `to_html` function to call it later
      pd.DataFrame.base_to_html = pd.DataFrame.to_html
      # Call it here in a controlled way
      pd.DataFrame.to_html = (
          lambda df, *args, **kwargs: 
              (df.base_to_html(*args, **kwargs)
                 .replace(r"\n", "<br/>"))
      )
      

      这样,您不需要在 Jupyter 笔记本中调用任何显式函数,因为 to_html 是在内部调用的。如果您想要原始功能,请致电base_to_html(或您命名的任何名称)。

      我正在使用jupyter 1.0.0notebook 5.7.6

      【讨论】:

      • 这是否可以在 python 脚本中使用 - 没有 jupyter 笔记本?
      【解决方案3】:

      如果你想在 ipython notebook 中这样做,你可以这样做:

      from IPython.display import display, HTML
      
      def pretty_print(df):
          return display( HTML( df.to_html().replace("\\n","<br>") ) )
      

      【讨论】:

      • 快速干净,无需更改设置,只是笔记本专用的 oneliner。这是给我的。
      【解决方案4】:

      来自 pandas.DataFrame documention

      二维大小可变、可能异构的表格数据 带有标记轴(行和列)的结构。算术运算 在行和列标签上对齐。可以认为是dict-like 系列对象的容器。 pandas 的主要数据结构

      所以你不能有没有索引的行。换行符“\n”在 DataFrame 中不起作用。

      您可以用空值覆盖“pos”,并在下一行输出下一个“投标人”。但是每次你这样做时 index 和 'pos' 都会被抵消。喜欢:

        pos    bidder
      0   1          
      1   2          
      2   3  <- alice
      3        <- bob
      4   5   
      

      因此,如果名为“frank”的投标人的价值为 4,它将覆盖“bob”。当您添加更多内容时,这会导致问题。可能可以使用 DataFrame 并编写代码来解决此问题,但可能值得研究其他解决方案。

      这是生成上述输出结构的代码。

      import pandas as pd
      
      n = 5
      output = pd.DataFrame({'pos': range(1, n + 1),
                            'bidder': [''] * n},
                            columns=['pos', 'bidder'])
      bids = {'alice': 3, 'bob': 3}
      used_pos = []
      for bidder, pos in bids.items():
          if pos in used_pos:
              output.ix[pos, 'bidder'] = "<- %s" % bidder
              output.ix[pos, 'pos'] = ''
          else:
              output.ix[pos - 1, 'bidder'] = "<- %s" % bidder
              used_pos.append(pos)
      print(output)
      

      编辑:

      另一种选择是重组数据和输出。你可以 将 pos 作为列,并为每个键/人创建一个新行 在数据中。在下面的代码示例中,它使用 NaN 打印 DataFrame 值替换为空字符串。

      import pandas as pd
      
      data = {'johnny\nnewline': 2, 'alice': 3, 'bob': 3,
              'frank': 4, 'lisa': 1, 'tom': 8}
      n = range(1, max(data.values()) + 1)
      
      # Create DataFrame with columns = pos
      output = pd.DataFrame(columns=n, index=[])
      
      # Populate DataFrame with rows
      for index, (bidder, pos) in enumerate(data.items()):
          output.loc[index, pos] = bidder
      
      # Print the DataFrame and remove NaN to make it easier to read.
      print(output.fillna(''))
      
      # Fetch and print every element in column 2
      for index in range(1, 5):
          print(output.loc[index, 2])
      

      不过,这取决于您想对数据做什么。祝你好运:)

      【讨论】:

      • 很有趣,尽管我在定义中没有看到任何阻止 DataFrame 包含换行符 inside 元素的内容。例如,该原理在 R 中运行良好。无论哪种方式,我可能最终都会使用字符串格式逐行进行。
      • 如果您从包含例如 'johnny\nnewline' 的 DataFrame 中获取一个元素并打印它,它将在一行上打印 'johnny' 并在新行上打印 'newline'。添加另一个选项,并打印示例以回答。
      猜你喜欢
      • 2013-07-07
      • 2015-04-05
      • 1970-01-01
      • 2013-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多