pandas 如何从数组列中提取数组元素?

nukf8bse  于 2022-12-28  发布在  其他
关注(0)|答案(3)|浏览(335)

我正在使用一个数据集,可以在这里找到:https://www.kaggle.com/datasets/lehaknarnauli/spotify-datasets?select=artists.csv。我想做的是提取列genres中每个数组的第一个元素。例如,如果我得到了['pop','rock'],我想提取'pop'。我尝试了不同的方法,但没有一个有效,我不知道为什么。
下面是我的代码:

import pandas as pd

df = pd.read_csv('artists.csv')

# approach 1
df['top_genre'] = df['genres'].str[0]
# Error: 'str' object has no attribute 'str'

# approach 2
df = df.assign(top_genre = lambda x: df['genres'].str[0])
# The result is single bracket '[' in each row. Seems like index=0 refers to first character of a string, not first array element.

# approach 3
df['top_genre'] = df['genres'].apply(lambda x: '[]' if not x else x[0])
# The result is single bracket '[' in each row. Seems like index=0 refers to first character of a string, not first array element.

为什么这些方法不起作用,如何使它起作用?

xeufq47z

xeufq47z1#

在您的代码中,genres列是流派列表的字符串表示形式,这意味着该列中的每个值都是括在方括号([])中的字符串。
要提取列表的第一个元素,首先需要使用ast模块中的ast.literal_eval函数将字符串转换为列表。此函数安全地计算包含文字Python对象的字符串,并返回相应的对象。然而,由于某些行为None,因此在调用ast.literal_eval之前,应应用一个函数检查值是否为空列表:

import ast

def get_top_genre(x):
    if x == '[]':
        return None
    return ast.literal_eval(x)[0]

df['top_genre'] = df['genres'].apply(get_top_genre)
bis0qfac

bis0qfac2#

另一种方法是:

import json
df["top_genre"]=df["genres"].apply(lambda x: None if x == '[]' else json.loads(x)[0])
iugsix8n

iugsix8n3#

您的genres列实际上似乎不是一个列表,而是一个包含列表(如"['a', 'b']")的字符串。您将不得不对字符串使用eval,以便再次将每行转换为列表对象,但出于安全原因,最好使用ast.literal_eval

在读取数据集期间使用Converter

一种方法是使用converters参数在加载数据集本身时应用转换器。这种方法的优点是可以使用单个字典执行多个转换和类型转换,如果需要,可以同时应用于大量类似的文件。

from ast import literal_eval

df = pd.read_csv('/path_do_data/artists.csv', 
                 converters={'genres': literal_eval})
df['genres'].str[0]
0                        NaN
1                        NaN
2                        NaN
3                        NaN
4                        NaN
                 ...        
1104344                  NaN
1104345    deep acoustic pop
1104346                  NaN
1104347                  NaN
1104348                  NaN

对列使用apply方法

另一种解决方法是使用literal_eval转换字符串。这一步需要多行代码来覆盖现有的列,但也能正常工作,只是在我看来有点多余。
一个二个一个一个

相关问题