使用列表理解 Python 创建新列
Posted
技术标签:
【中文标题】使用列表理解 Python 创建新列【英文标题】:Create New Column With List Comprehension Python 【发布时间】:2021-01-21 13:16:51 【问题描述】:我正在尝试创建一个包含城市名称的新列。我还有一个列表,其中包含所需的城市名称以及在不同列名下具有城市名称的 CSV 文件。
我要做的是检查列表中的城市名称是否存在于 CSV 文件的特定列范围内,并将该特定城市名称填写在新列 City 中。
我的代码是:
import pandas as pd
import numpy as np
City_Name_List = ['Amsterdam', 'Antwerp', 'Brussels', 'Ghent', 'Asheville', 'Austin', 'Boston', 'Broward County',
'Cambridge', 'Chicago', 'Clark County Nv', 'Columbus', 'Denver', 'Hawaii', 'Jersey City', 'Los Angeles',
'Nashville', 'New Orleans', 'New York City', 'Oakland', 'Pacific Grove', 'Portland', 'Rhode Island', 'Salem Or', 'San Diego']
data = 'host_identity_verified':['t','t','t','t','t','t','t','t','t','t'],
'neighbourhood':['Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands', 'NaN',
'Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands',
'Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands', 'NaN',
'Amsterdam, North Holland, Netherlands', 'Amsterdam, North Holland, Netherlands'],
'neighbourhood_cleansed':['Oostelijk Havengebied - Indische Buurt', 'Centrum-Oost', 'Centrum-West', 'Centrum-West', 'Centrum-West',
'Oostelijk Havengebied - Indische Buurt', 'Centrum-Oost', 'Centrum-West', 'Centrum-West', 'Centrum-West'],
'neighbourhood_group_cleansed': ['NaN','NaN','NaN','NaN','NaN','NaN','NaN','NaN','NaN','NaN'],
'latitude':[ 52.36575, 52.36509, 52.37297, 52.38761, 52.36719, 52.36575, 52.36509, 52.37297, 52.38761, 52.36719]
df = pd.DataFrame(data)
df['City'] = [x for x in City_Name_List if x in df.loc[:,'host_identity_verified':'latitude'].values][0]
当我运行代码时,我收到以下消息:
Traceback (most recent call last):
File "C:/Users/YAZAN/PycharmProjects/Yazan_Work/try.py", line 63, in <module>
df['City'] = [x for x in City_Name_List if x in df.loc[:,'host_identity_verified':'latitude'].values][0]
IndexError: list index out of range
这是由于数据中的City Amsterdam后面是其他词。
我希望我的输出如下:
0 Amsterdam
1 Amsterdam
2 Amsterdam
3 Amsterdam
4 Amsterdam
5 Amsterdam
6 Amsterdam
7 Amsterdam
8 Amsterdam
9 Amsterdam
Name: City, dtype: object
我不断尝试解决这个问题。我尝试使用endswith
、startswith
、正则表达式,但无济于事。我可能错误地使用了这两种方法。我希望有人可以帮助我。
【问题讨论】:
【参考方案1】:使用Pandas.DataFrame.Apply
的基本解决方案
df['City'] = df.apply(
lambda row: [x if x in row.loc['neighbourhood'] for x in City_Name_List][0],
axis=1
)
执行上述操作后,如果在每行的 'neighbourhood'
列中找到一个城市,df['city']
将包含一个城市(由其包含在 City_Name_List
中定义)。
修改方案
您可以更明确地指定City
应填充在每行的'neighbourhood'
字段中第一次出现,
之前存在的第一个子字符串上。如果'neighbourhood'
列在结构上可靠统一,这可能是一个好主意,因为它可以帮助减轻由类似名称的城市、作为City_Name_List
中其他城市的子字符串的城市等引起的任何不良行为。
df['City'] = df.apply(
lambda row: [x if x in row.loc['neighbourhood'].split(',')[0] for x in City_Name_List][0],
axis=1
)
注意:上述解决方案只是您如何解决您遇到的问题的示例。它们没有考虑对异常、边缘情况等的正确处理。与以往一样,您应该注意在代码中考虑这些因素。
【讨论】:
感谢您的回答。在应用您的代码时,我还在新列中得到了 NaN。但是我将 np.nan 更改为 x 并用所需的城市名称填充它。非常感激。一个小问题,并不是我所有的数据文件都在一个名为邻域的列中包含城市名称,我知道城市名称位于列 host_identity_verified 和纬度之间。如何更改代码以捕获它?【参考方案2】:df['City'] = df['neighbourhood'].apply(lambda x: [i for i in x.split(',') if i in City_Name_List])
df['City'] = df['City'].apply(lambda x: "" if len(x) == 0 else x[0])
【讨论】:
Apply 比 pandas 中的矢量化Series.str
方法慢
请提交矢量化答案:)
感谢您的回答。我部分得到了我想要的,但是当原始列中有 NaN 值时,该行在新列中变为空。还有一件事,因为我正在处理 2000 多个 CSV 文件,并且并非所有文件都有名为 neighbourhood 的列,但我知道城市名称位于 host_identity_verified 和 latitude 列之间,是否可以保留 df .loc[:,'host_identity_verified':'latitude'] 在代码中?
@LiamFiddler 的答案中的 df['neighbourhood'].str.split(',')[0]
是 pandas 中矢量化 str 方法的一个示例,您可能已经知道了。它至少删除了一个应用或列表理解。我感觉他的用例比容易回答的要复杂。
我的索引器放错了位置,导致它运行不正确,但整体解决方案有效。【参考方案3】:
问题在于,当您说x in df.loc[]
时,您不是在检查城市名称是否在每个特定字符串中,而是在检查城市名称是否在整个系列中,而事实并非如此。你需要的是这样的:
df['city'] = [x if x in City_Name_list else '' for x[0] in df['neighbourhood'].str.split(',')]
这将沿逗号分隔 df['neighborhood'] 中的每一行并返回第一个值,然后检查该值是否在您的城市名称列表中,如果是,则将其放入“城市”系列中。
【讨论】:
运行代码时出现此错误:“值长度” ValueError:值长度 (1) 与索引长度 (10) 不匹配 哦,抱歉,我没有看到所有数据并意识到存在 NaN 值。该列表理解中需要有一个 else 子句。 这将导致数据框中的每个值都没有城市值,因此不同的长度会导致问题。我已经更新了我的答案。 很抱歉,代码仍然无效。我真的很感谢你花时间检查我的问题。非常感谢。 我意识到我放错了索引器。 [0] 应该在 x 之后,而不是 .str.split() 方法。在该方法上调用 [0] 仅返回数据框中的第一行。答案已修复,但很高兴看到您找到了可行的解决方案。以上是关于使用列表理解 Python 创建新列的主要内容,如果未能解决你的问题,请参考以下文章
使用 PySpark 中的列表中的 withColumn 函数动态创建新列