For Loop in Python Error: The truth value of a Series is ambiguous
For Loop in Python Error: The truth value of a Series is ambiguous
为什么这个 for 循环不起作用...?
我想得到一个包含交货年份的新列,它由这些列组成,但是,有很多 Nans,所以逻辑是 for 循环遍历列并且 returns 第一个非-Na值。最好的情况是交货日期,如果不存在,那么构建年份,如果即使不存在,那么至少机器投入使用时的投入使用日期。
df = pd.DataFrame({'Platform ID' : [1,2,3,4], "Delivery Date" : [str(2009), float("nan"), float("nan"), float("nan")],
"Build Year" : [float("nan"),str(2009),float("nan"), float("nan")],
"In Service Date" : [float("nan"),str("14-11-2010"), str("14-11-2009"), float("nan")]})
df.dtypes
df
def delivery_year(delivery_year, build_year, service_year):
out = []
for i in range(0,len(delivery_year)):
if delivery_year.notna():
out[i].append(delivery_year)
if (delivery_year[i].isna() and build_year[i].notna()):
out[i].append(build_year)
elif build_year[i].isna():
out[i].append(service_year.str.strip().str[-4:])
else:
out[i].append(float("nan"))
return out
df["Delivery Year"] = delivery_year(df["Delivery Date"], df["Build Year"], df["In Service Date"])
当我 运行 这个函数时,我得到这个错误,我不知道为什么...
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
预期产量(交货年份列):
更新 3
我以与您相同的方式重写了您的函数,因此没有改变您的列的逻辑和类型。我让你比较两个版本:
def delivery_year(delivery_date, build_year, service_year):
out = []
for i in range(len(delivery_date)):
if pd.notna(delivery_date[i]):
out.append(delivery_date[i])
elif pd.isna(delivery_date[i]) and pd.notna(build_year[i]):
out.append(build_year[i])
elif pd.isna(build_year[i]) and pd.notna(service_year[i]):
out.append(service_year[i].strip()[-4:])
else:
out.append(float("nan"))
return out
df["Delivery Year"] = delivery_year(df["Delivery Date"],
df["Build Year"],
df["In Service Date"])
备注:
我更改了你的第一个参数的名称,因为 delivery_year
也是你的函数的名称,所以它可能会造成混淆。
我还用它们的等效函数替换了 .isna()
和 .notna()
方法:pd.isna(...)
和 pd.notna(...)
。
第二个if
变成了elif
更新 2
使用combine_first
替换你的函数。 combine_first
使用值为 NaN
的第二个系列更新第一个系列 ('Delivery Date')。您可以将它们链接起来以填充您的 'Delivery Year'.
df['Delivery Year'] = df['Delivery Date'] \
.combine_first(df['Build Year']) \
.combine_first(df['In Service Date'].str[-4:])
输出:
>>> df
Platform ID Delivery Date Build Year In Service Date Delivery Year
0 1 2009 NaN NaN 2009
1 2 NaN 2009 14-11-2010 2009
2 3 NaN NaN 14-11-2009 2009
3 4 NaN NaN NaN NaN
更新
您忘记了 [i]
:
if delivery_year[i].notna():
Series 的真值不明确:
>>> delivery_year.notna()
0 True # <- 2009
1 False # <- NaN
2 False
3 False
Name: Delivery Date, dtype: bool
Pandas 应该考虑该系列是 True (2009) 还是 False (NaN)?
您必须将结果与 .any()
或 .all()
相加
>>> delivery_year.notna().any()
True # because there is at least one non nan-value.
>>> delivery_year.notna().all()
False # because all values are not nan.
据我所知,你的错误有解决方案。
如果您想在第一次出现 Non-nan 值时触发 IF 语句,
像这样使用 .any()。
if delivery_year.notna().any():
out[i].append(delivery_year)
您必须指定是否要从特定列或 'All' 值中过滤掉 'Any' 值。
:)
报错的原因之一是虽然你的Delivery Date、Build Year和In Service Date是object类型,但是其中的NaN值是float类型(见下图)
解决这个问题的方法之一是将三列转换为 str 类型:
df["Delivery Date"] = df["Delivery Date"].astype(str)
df["Build Year"] = df["Build Year"].astype(str)
df["In Service Date"] = df["In Service Date"].astype(str)
然后我修改了你的函数如下:
def delivery_year(delivery_year, build_year, service_year):
out = []
for i in range(0,len(delivery_year)):
if len(delivery_year[i])>=4:
out.append(delivery_year[i])
elif (len(delivery_year[i])<4) & (len(build_year[i])>=4):
out.append(build_year[i])
elif (len(build_year[i])<4 and len(service_year[i])>=4):
out.append(service_year[i].split("-")[-1])
else:
out.append(float("nan"))
return out
df["Delivery Year"] = delivery_year(df["Delivery Date"], df["Build Year"], df["In Service Date"])
我正在检查大于 4 的长度,因为“NaN”作为字符串的长度将在上面的函数中检查为 3。这将 return 您需要的附加列,如附上屏幕截图
为什么这个 for 循环不起作用...?
我想得到一个包含交货年份的新列,它由这些列组成,但是,有很多 Nans,所以逻辑是 for 循环遍历列并且 returns 第一个非-Na值。最好的情况是交货日期,如果不存在,那么构建年份,如果即使不存在,那么至少机器投入使用时的投入使用日期。
df = pd.DataFrame({'Platform ID' : [1,2,3,4], "Delivery Date" : [str(2009), float("nan"), float("nan"), float("nan")],
"Build Year" : [float("nan"),str(2009),float("nan"), float("nan")],
"In Service Date" : [float("nan"),str("14-11-2010"), str("14-11-2009"), float("nan")]})
df.dtypes
df
def delivery_year(delivery_year, build_year, service_year):
out = []
for i in range(0,len(delivery_year)):
if delivery_year.notna():
out[i].append(delivery_year)
if (delivery_year[i].isna() and build_year[i].notna()):
out[i].append(build_year)
elif build_year[i].isna():
out[i].append(service_year.str.strip().str[-4:])
else:
out[i].append(float("nan"))
return out
df["Delivery Year"] = delivery_year(df["Delivery Date"], df["Build Year"], df["In Service Date"])
当我 运行 这个函数时,我得到这个错误,我不知道为什么...
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
预期产量(交货年份列):
更新 3
我以与您相同的方式重写了您的函数,因此没有改变您的列的逻辑和类型。我让你比较两个版本:
def delivery_year(delivery_date, build_year, service_year):
out = []
for i in range(len(delivery_date)):
if pd.notna(delivery_date[i]):
out.append(delivery_date[i])
elif pd.isna(delivery_date[i]) and pd.notna(build_year[i]):
out.append(build_year[i])
elif pd.isna(build_year[i]) and pd.notna(service_year[i]):
out.append(service_year[i].strip()[-4:])
else:
out.append(float("nan"))
return out
df["Delivery Year"] = delivery_year(df["Delivery Date"],
df["Build Year"],
df["In Service Date"])
备注:
我更改了你的第一个参数的名称,因为
delivery_year
也是你的函数的名称,所以它可能会造成混淆。我还用它们的等效函数替换了
.isna()
和.notna()
方法:pd.isna(...)
和pd.notna(...)
。第二个
if
变成了elif
更新 2
使用combine_first
替换你的函数。 combine_first
使用值为 NaN
的第二个系列更新第一个系列 ('Delivery Date')。您可以将它们链接起来以填充您的 'Delivery Year'.
df['Delivery Year'] = df['Delivery Date'] \
.combine_first(df['Build Year']) \
.combine_first(df['In Service Date'].str[-4:])
输出:
>>> df
Platform ID Delivery Date Build Year In Service Date Delivery Year
0 1 2009 NaN NaN 2009
1 2 NaN 2009 14-11-2010 2009
2 3 NaN NaN 14-11-2009 2009
3 4 NaN NaN NaN NaN
更新
您忘记了 [i]
:
if delivery_year[i].notna():
Series 的真值不明确:
>>> delivery_year.notna()
0 True # <- 2009
1 False # <- NaN
2 False
3 False
Name: Delivery Date, dtype: bool
Pandas 应该考虑该系列是 True (2009) 还是 False (NaN)?
您必须将结果与 .any()
或 .all()
>>> delivery_year.notna().any()
True # because there is at least one non nan-value.
>>> delivery_year.notna().all()
False # because all values are not nan.
据我所知,你的错误有解决方案。 如果您想在第一次出现 Non-nan 值时触发 IF 语句, 像这样使用 .any()。
if delivery_year.notna().any():
out[i].append(delivery_year)
您必须指定是否要从特定列或 'All' 值中过滤掉 'Any' 值。 :)
报错的原因之一是虽然你的Delivery Date、Build Year和In Service Date是object类型,但是其中的NaN值是float类型(见下图)
解决这个问题的方法之一是将三列转换为 str 类型:
df["Delivery Date"] = df["Delivery Date"].astype(str)
df["Build Year"] = df["Build Year"].astype(str)
df["In Service Date"] = df["In Service Date"].astype(str)
然后我修改了你的函数如下:
def delivery_year(delivery_year, build_year, service_year):
out = []
for i in range(0,len(delivery_year)):
if len(delivery_year[i])>=4:
out.append(delivery_year[i])
elif (len(delivery_year[i])<4) & (len(build_year[i])>=4):
out.append(build_year[i])
elif (len(build_year[i])<4 and len(service_year[i])>=4):
out.append(service_year[i].split("-")[-1])
else:
out.append(float("nan"))
return out
df["Delivery Year"] = delivery_year(df["Delivery Date"], df["Build Year"], df["In Service Date"])
我正在检查大于 4 的长度,因为“NaN”作为字符串的长度将在上面的函数中检查为 3。这将 return 您需要的附加列,如附上屏幕截图