【问题标题】:pandas - convert string into list of strings [duplicate]pandas - 将字符串转换为字符串列表[重复]
【发布时间】:2018-01-27 06:11:42
【问题描述】:

我有这个“file.csv”文件可以用 pandas 读取:

Title|Tags
T1|"[Tag1,Tag2]"
T1|"[Tag1,Tag2,Tag3]"
T2|"[Tag3,Tag1]"

使用

df = pd.read_csv('file.csv', sep='|')

输出是:

  Title              Tags
0    T1       [Tag1,Tag2]
1    T1  [Tag1,Tag2,Tag3]
2    T2       [Tag3,Tag1]

我知道Tags 列是一个完整的字符串,因为:

In [64]: df['Tags'][0][0]
Out[64]: '['

我需要将其读取为字符串列表,例如["Tag1","Tag2"]。我尝试了this 问题中提供的解决方案,但没有运气,因为我的[] 字符实际上把事情搞砸了。

预期的输出应该是:

In [64]: df['Tags'][0][0]
Out[64]: 'Tag1'

【问题讨论】:

标签: python string pandas csv


【解决方案1】:

您可以手动拆分字符串:

>>> df['Tags'] = df.Tags.apply(lambda x: x[1:-1].split(','))
>>> df.Tags[0]
['Tag1', 'Tag2']

【讨论】:

  • 或者在加载时应用...df = pd.read_csv('file.csv', sep='|', converters={'Tags': lambda x: x[1:-1].split(',')})
  • @JonClements, converters={'Tags': lambda x: x[1:-1].split(',')} 让我省了很多麻烦。谢谢你。
【解决方案2】:

或者

df.Tags=df.Tags.str[1:-1].str.split(',').tolist()

【讨论】:

  • @WeNToBen - 不错的解决方案。想扩大一点吗?为什么我们需要str[1:-1],为什么不需要str[0:-1]? (顺便说一句,对我来说,两者都产生相同的结果)。另外,如果split() 已经创建了一个列表,为什么还要显式调用tolist()
  • @zerohedge 因为你想删除开头的“[”和结尾的“]”
  • 谢谢。为什么tolist()split() 之后(它本身会创建一个列表,不是吗?)
  • @zerohedge 啊,我需要删除的那个,你说得对
【解决方案3】:

我认为你可以使用 json 模块。

import json
import pandas

df = pd.read_csv('file.csv', sep='|')
df['Tags'] = df['Tags'].apply(lambda x: json.loads(x))

所以这将像以前一样加载您的数据框,然后将 lambda 函数应用于Tags 列中的每个项目。 lambda 函数调用 json.loads() 将列表的字符串表示形式转换为实际列表。

【讨论】:

  • 我认为这是一个更好的解决方案,更不容易出错!另外请注意,您可以将json.loads 直接作为apply 参数传递:df['Tags'].apply(json.loads)
【解决方案4】:

您可以使用stripsplit 将字符串转换为列表。

df_out = df.assign(Tags=df.Tags.str.strip('[]').str.split(','))

df_out.Tags[0][0]

输出:

'Tag1'

【讨论】:

    【解决方案5】:

    您可以使用内置的ast.literal_eval,它适用于元组和列表

    import ast
    import pandas as pd
    
    df = pd.DataFrame({"mytuples": ["(1,2,3)"]})
    
    print(df.iloc[0,0])
    # >> '(1,2,3)'
    
    df["mytuples"] = df["mytuples"].apply(ast.literal_eval)
    
    print(df.iloc[0,0])
    # >> (1,2,3)
    

    编辑:eval 应该避免!如果正在评估的字符串是os.system(‘rm -rf /’),它将开始删除您计算机上的所有文件(here)。对于ast.literal_eval,提供的字符串或节点只能包含以下 Python 文字结构:字符串、字节、数字、元组、列表、字典、集合、布尔值和无 (here)。谢谢@TrentonMcKinney :)

    【讨论】:

      【解决方案6】:

      您的df['Tags'] 似乎是一个字符串列表。如果您打印该列表,您应该得到 ["[tag1,tag2]","[Tag1,Tag2,Tag3]","[Tag3,Tag1]"] 这就是为什么当您调用第一个元素的第一个元素时,您实际上得到的是字符串的第一个单个字符,而不是您想要的。

      您要么需要在之后解析该字符串。执行类似的操作

      df['Tags'][0] = df['Tags'][0].split(',')
      

      但是正如您在引用的示例中看到的那样,这会给您一个看起来像

      的列表
      in: df['Tags'][0][0] 
      out: '[tag1'`
      

      您需要的是一种解析字符串并编辑出多个字符的方法。您可以使用简单的正则表达式来执行此操作。比如:

       import re
       df['Tags'][0] = re.findall(r"[\w']+", df['Tags'][0])
       print(df['Tags'][0][0])
      

      将打印:

       'tag1'
      

      使用涉及 Pandas 转换器的其他答案,您可以编写如下转换器:

       def clean(seq_string):
            return re.findall(r"[\w']+", seq_string)
      

      如果您不了解正则表达式,它们可能非常强大,但如果您不确定输入字符串的内容,它们也会变得不可预测。此处使用的表达式r"[\w']+" 将匹配任何常见的单词字符字母数字和下划线,并将其他所有内容视为re.findall 拆分列表的点。

      【讨论】:

        【解决方案7】:

        这是一个简单而高效的操作:

        df['Tags'].str.split(',')
        

        【讨论】:

        • 不去掉开头和结尾的方括号
        猜你喜欢
        • 2011-05-27
        • 2016-07-05
        • 2011-02-23
        • 2017-06-28
        • 1970-01-01
        • 2016-09-17
        • 2020-11-20
        • 2019-10-25
        • 1970-01-01
        相关资源
        最近更新 更多