Pandas - 设置列值,基于在另一列上运行的函数
Pandas - Setting column value, based on a function that runs on another column
我到处都在尝试让它工作(数据科学的新手)。这显然是因为我不明白 Panda 的数据结构是如何工作的。
我有这个代码:
def getSearchedValue(identifier):
full_str = anedf["Diskret data"].astype(str)
value=""
if full_str.str.find(identifier) <= -1:
start_index = full_str.str.find(identifier)+len(identifier)+1
end_index = full_str[start_index:].find("|")+start_index
value = full_str[start_index:end_index].astype(str)
return value
for col in anedf.columns:
if col.count("#") > 0:
anedf[col] = getSearchedValue(col)
我想做的是遍历我的专栏。我的数据框中有大约 260 个。如果它们包含字符 #,它应该尝试根据我的“Diskret 数据”列中的内容填充值。
“Diskret 数据”列中的数据完全混乱,但格式为 CCC#111~VALUE|DDD#222~VALUE|
<- 直到没有更多的标识符 + 值。并非所有标识符都出现在每一行中,并且它们没有特定的顺序。
如果我 运行 它在常规 Python 文档中使用硬编码字符串,则该函数有效。但是对于数据框,我得到了各种错误,例如:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Input In [119], in <cell line: 12>()
12 for col in anedf.columns:
13 if col.count("#") > 0:
---> 14 anedf[col] = getSearchedValue(col)
Input In [119], in getSearchedValue(identifier)
4 full_str = anedf["Diskret data"].astype(str)
5 value=""
----> 6 if full_str.str.find(identifier) <= -1:
7 start_index = full_str.str.find(identifier)+len(identifier)+1
8 end_index = full_str[start_index:].find("|")+start_index
我想这是因为它针对所有行(系列)进行评估,这显然会提供一些错误和正确的错误。但是我怎样才能进行评估和分配,所以它是这样评估+分配的:
Diskret data
CCC#111
JJSDJ#1234
CCC#111~1IBBB#2323~2234
1 (copied from "Diskret data")
0
JJSDJ#1234~Heart attack
0 (or skipped since the row does not contain a value for the identifier)
Heart attack
计划是在分配完成后删除“Diskret 数据”,这样我的数据就更有条理了。
---更新---
根据要求:
我附上了一张图片,展示了我如何想象这个问题,以及我似乎无法做到的事情。
使用正则表达式,您可以执行以下操作:
def map_(list_) -> pd.Series:
if list_:
idx, values = zip(*list_)
return pd.Series(values, idx)
else:
return pd.Series(dtype=object)
series = pd.Series(
['CCC#111~1|BBB#2323~2234', 'JJSDJ#1234~Heart attack']
)
reg_series = series.str.findall(r'([^~|]+)~([^~|]+)')
reg_series.apply(map_)
分解:
通过运行在每一行上创建一个映射,将长字符串变成元组列表来创建一个新系列
通过 运行 在每一行上创建一个映射,将长字符串变成元组列表来创建一个新系列。
reg_series = series.str.findall(r'([^~|]+)~([^~|]+)')
reg_series
# output:
# 0 [(CCC#111, 1), (BBB#2323, 2234)]
# 1 [(JJSDJ#1234, Heart attack)]
然后我们创建一个map_
函数。此函数获取 reg_series
的每一行并将其映射到两行:第一行仅包含“键”,另一行仅包含“值”。然后我们创建一系列这样的索引作为键和值作为值。
编辑: 我们在 if
/else
语句中添加了检查列表是否存在的语句。如果没有,我们 return 一个空系列的类型对象。
def map_(list_) -> pd.Series:
if list_:
idx, values = zip(*list_)
return pd.Series(values, idx)
else:
return pd.Series(dtype=object)
...
print(idx, values) # first row
# output:
# ('CCC#111', 'BBB#2323') (1, 2234)
最后,我们 运行 apply
在该系列中创建一个数据框,该数据框从 map_
获取每一行的输出,并以柱状格式将它们压缩在一起。
reg_series.apply(map_)
# output:
# CCC#111 BBB#2323 JJSDJ#1234
# 0 1 2234 NaN
# 1 NaN NaN Heart attack
我到处都在尝试让它工作(数据科学的新手)。这显然是因为我不明白 Panda 的数据结构是如何工作的。
我有这个代码:
def getSearchedValue(identifier):
full_str = anedf["Diskret data"].astype(str)
value=""
if full_str.str.find(identifier) <= -1:
start_index = full_str.str.find(identifier)+len(identifier)+1
end_index = full_str[start_index:].find("|")+start_index
value = full_str[start_index:end_index].astype(str)
return value
for col in anedf.columns:
if col.count("#") > 0:
anedf[col] = getSearchedValue(col)
我想做的是遍历我的专栏。我的数据框中有大约 260 个。如果它们包含字符 #,它应该尝试根据我的“Diskret 数据”列中的内容填充值。
“Diskret 数据”列中的数据完全混乱,但格式为 CCC#111~VALUE|DDD#222~VALUE|
<- 直到没有更多的标识符 + 值。并非所有标识符都出现在每一行中,并且它们没有特定的顺序。
如果我 运行 它在常规 Python 文档中使用硬编码字符串,则该函数有效。但是对于数据框,我得到了各种错误,例如:
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
Input In [119], in <cell line: 12>()
12 for col in anedf.columns:
13 if col.count("#") > 0:
---> 14 anedf[col] = getSearchedValue(col)
Input In [119], in getSearchedValue(identifier)
4 full_str = anedf["Diskret data"].astype(str)
5 value=""
----> 6 if full_str.str.find(identifier) <= -1:
7 start_index = full_str.str.find(identifier)+len(identifier)+1
8 end_index = full_str[start_index:].find("|")+start_index
我想这是因为它针对所有行(系列)进行评估,这显然会提供一些错误和正确的错误。但是我怎样才能进行评估和分配,所以它是这样评估+分配的:
Diskret data | CCC#111 | JJSDJ#1234 |
---|---|---|
CCC#111~1IBBB#2323~2234 | 1 (copied from "Diskret data") | 0 |
JJSDJ#1234~Heart attack | 0 (or skipped since the row does not contain a value for the identifier) | Heart attack |
计划是在分配完成后删除“Diskret 数据”,这样我的数据就更有条理了。
---更新--- 根据要求:
我附上了一张图片,展示了我如何想象这个问题,以及我似乎无法做到的事情。
使用正则表达式,您可以执行以下操作:
def map_(list_) -> pd.Series:
if list_:
idx, values = zip(*list_)
return pd.Series(values, idx)
else:
return pd.Series(dtype=object)
series = pd.Series(
['CCC#111~1|BBB#2323~2234', 'JJSDJ#1234~Heart attack']
)
reg_series = series.str.findall(r'([^~|]+)~([^~|]+)')
reg_series.apply(map_)
分解:
通过运行在每一行上创建一个映射,将长字符串变成元组列表来创建一个新系列
通过 运行 在每一行上创建一个映射,将长字符串变成元组列表来创建一个新系列。
reg_series = series.str.findall(r'([^~|]+)~([^~|]+)')
reg_series
# output:
# 0 [(CCC#111, 1), (BBB#2323, 2234)]
# 1 [(JJSDJ#1234, Heart attack)]
然后我们创建一个map_
函数。此函数获取 reg_series
的每一行并将其映射到两行:第一行仅包含“键”,另一行仅包含“值”。然后我们创建一系列这样的索引作为键和值作为值。
编辑: 我们在 if
/else
语句中添加了检查列表是否存在的语句。如果没有,我们 return 一个空系列的类型对象。
def map_(list_) -> pd.Series:
if list_:
idx, values = zip(*list_)
return pd.Series(values, idx)
else:
return pd.Series(dtype=object)
...
print(idx, values) # first row
# output:
# ('CCC#111', 'BBB#2323') (1, 2234)
最后,我们 运行 apply
在该系列中创建一个数据框,该数据框从 map_
获取每一行的输出,并以柱状格式将它们压缩在一起。
reg_series.apply(map_)
# output:
# CCC#111 BBB#2323 JJSDJ#1234
# 0 1 2234 NaN
# 1 NaN NaN Heart attack