如何从列表中提取数据作为字符串,并在 pandas 中按值提取 select 数据?
How to extract data from lists as strings, and select data by value, in pandas?
我有一个这样的数据框:
col1 col2
[abc, bcd, dog] [[.4], [.5], [.9]]
[cat, bcd, def] [[.9], [.5], [.4]]
col2
列表中的数字描述了 col1
中的元素(基于列表索引位置)。所以 col2
中的“.4”描述了 col1
中的“abc”。
我想创建 2 个新列,一个只提取 col1
中 >= .9 col2
中的元素,另一列作为 [=15= 中的数字];所以两行都是“.9”。
结果:
col3 col4
[dog] .9
[cat] .9
我认为从 col2
中删除嵌套列表的方法很好。但这比听起来要难。我已经尝试了一个小时来删除那些 fing 括号。
尝试次数:
spec_chars3 = ["[","]"]
for char in spec_chars3: # didn't work, turned everything to nan
df1['avg_jaro_company_word_scores'] = df1['avg_jaro_company_word_scores'].str.replace(char, '')
df.col2.str.strip('[]') #didn't work b/c the nested list is still in a list, not a string
我什至还没有想出如何提取列表索引号并在其上过滤 col1
- 根据题尾的解释,好像两列都是
str
类型,需要转成list
类型
- 将
.applymap
与 ast.literal_eval
结合使用。
- 如果只有一列是
str
类型,则使用df[col] = df[col].apply(literal_eval)
- 必须使用
pandas.DataFrame.explode
提取每列中的数据列表
- 正如 RichieV 在评论中阐明的那样:
-
lamdba
explode
不需要参数,因为它应用于每一列,并且 .apply
将所有输出收集到数据帧中。
- 外部
explode
将值从列表转换为标量(即 [0.4]
到 0.4
)。
- 一旦值位于不同的行上,使用所需范围内的 Boolean Indexing 到 select 数据。
- 如果您想将
df
与 df_new
结合使用,请使用 df.join(df_new, rsuffix='_extracted')
import pandas as pd
from ast import literal_eval
# setup the test data: this data is lists
# data = {'c1': [['abc', 'bcd', 'dog'], ['cat', 'bcd', 'def']], 'c2': [[[.4], [.5], [.9]], [[.9], [.5], [.4]]]}
# setup the test data: this data is strings
data = {'c1': ["['abc', 'bcd', 'dog', 'cat']", "['cat', 'bcd', 'def']"], 'c2': ["[[.4], [.5], [.9], [1.0]]", "[[.9], [.5], [.4]]"]}
# create the dataframe
df = pd.DataFrame(data)
# the description leads me to think the data is columns of strings, not lists
# convert the columns from string type to list type
# the following line is only required if the columns are strings
df = df.applymap(literal_eval)
# explode the lists in each column
df_new = df.apply(lambda x: x.explode()).explode('c2')
# use Boolean Indexing to select the desired data
df_new = df_new[df_new['c2'] >= 0.9]
# display(df_new)
c1 c2
0 dog 0.9
1 cat 0.9
您可以使用列表解析来根据您的条件填充新列。
df['col3'] = [
[value for value, score in zip(c1, c2) if score[0] >= 0.9]
for c1, c2 in zip(df['col1'], df['col2'])
]
df['col4'] = [
[score[0] for score in c2 if score[0] >= 0.9]
for c2 in df['col2']
输出
col1 col2 col3 col4
0 [abc, bcd, dog] [[0.4], [0.5], [0.9]] [dog] [0.9]
1 [cat, bcd, def] [[0.9], [0.5], [0.4]] [cat] [0.9]
我有一个这样的数据框:
col1 col2
[abc, bcd, dog] [[.4], [.5], [.9]]
[cat, bcd, def] [[.9], [.5], [.4]]
col2
列表中的数字描述了 col1
中的元素(基于列表索引位置)。所以 col2
中的“.4”描述了 col1
中的“abc”。
我想创建 2 个新列,一个只提取 col1
中 >= .9 col2
中的元素,另一列作为 [=15= 中的数字];所以两行都是“.9”。
结果:
col3 col4
[dog] .9
[cat] .9
我认为从 col2
中删除嵌套列表的方法很好。但这比听起来要难。我已经尝试了一个小时来删除那些 fing 括号。
尝试次数:
spec_chars3 = ["[","]"]
for char in spec_chars3: # didn't work, turned everything to nan
df1['avg_jaro_company_word_scores'] = df1['avg_jaro_company_word_scores'].str.replace(char, '')
df.col2.str.strip('[]') #didn't work b/c the nested list is still in a list, not a string
我什至还没有想出如何提取列表索引号并在其上过滤 col1
- 根据题尾的解释,好像两列都是
str
类型,需要转成list
类型- 将
.applymap
与ast.literal_eval
结合使用。 - 如果只有一列是
str
类型,则使用df[col] = df[col].apply(literal_eval)
- 将
- 必须使用
pandas.DataFrame.explode
提取每列中的数据列表- 正如 RichieV 在评论中阐明的那样:
-
lamdba
explode
不需要参数,因为它应用于每一列,并且.apply
将所有输出收集到数据帧中。 - 外部
explode
将值从列表转换为标量(即[0.4]
到0.4
)。
-
- 正如 RichieV 在评论中阐明的那样:
- 一旦值位于不同的行上,使用所需范围内的 Boolean Indexing 到 select 数据。
- 如果您想将
df
与df_new
结合使用,请使用df.join(df_new, rsuffix='_extracted')
import pandas as pd
from ast import literal_eval
# setup the test data: this data is lists
# data = {'c1': [['abc', 'bcd', 'dog'], ['cat', 'bcd', 'def']], 'c2': [[[.4], [.5], [.9]], [[.9], [.5], [.4]]]}
# setup the test data: this data is strings
data = {'c1': ["['abc', 'bcd', 'dog', 'cat']", "['cat', 'bcd', 'def']"], 'c2': ["[[.4], [.5], [.9], [1.0]]", "[[.9], [.5], [.4]]"]}
# create the dataframe
df = pd.DataFrame(data)
# the description leads me to think the data is columns of strings, not lists
# convert the columns from string type to list type
# the following line is only required if the columns are strings
df = df.applymap(literal_eval)
# explode the lists in each column
df_new = df.apply(lambda x: x.explode()).explode('c2')
# use Boolean Indexing to select the desired data
df_new = df_new[df_new['c2'] >= 0.9]
# display(df_new)
c1 c2
0 dog 0.9
1 cat 0.9
您可以使用列表解析来根据您的条件填充新列。
df['col3'] = [
[value for value, score in zip(c1, c2) if score[0] >= 0.9]
for c1, c2 in zip(df['col1'], df['col2'])
]
df['col4'] = [
[score[0] for score in c2 if score[0] >= 0.9]
for c2 in df['col2']
输出
col1 col2 col3 col4
0 [abc, bcd, dog] [[0.4], [0.5], [0.9]] [dog] [0.9]
1 [cat, bcd, def] [[0.9], [0.5], [0.4]] [cat] [0.9]