Pandas数据框:两列相乘

7

我试图在数据框架(OPR)中将两列相乘(ActualSalary * FTE),以创建一个新的列(FTESalary),但某种原因它停留在了第21357行,我不明白出了什么问题或如何修复。这两个列来自使用以下代码导入CSV文件:OPR = pd.read_csv('OPR.csv', encoding='latin1')

[In] OPR
[out]
ActualSalary    FTE
44600           1
58,000.00       1
70,000.00       1
17550           1
34693           1
15674           0.4

[In] OPR["FTESalary"] = OPR["ActualSalary"].str.replace(",", "").astype("float")*OPR["FTE"]
[In] OPR
[out]
ActualSalary    FTE FTESalary
44600           1   44600
58,000.00       1   58000
70,000.00       1   70000
17550           1   NaN
34693           1   NaN
15674           0.4 NaN

我并不希望输出结果中有任何NULL值,这真的让我很苦恼。如果能帮忙解决问题,我将非常感激。 万分感谢!(我对编码和这里都还很陌生,请通过私信告知我是否犯了错误或者需要改进我的提问方式) @oppresiveslayer分享数据。
[In] OPR[0:6].to_dict()
[out]
{'ActualSalary': {0: '44600',
1: '58,000.00',
2: '70,000.00',
3: '39,780.00',
4: '0.00',
5: '78,850.00'},
 'FTE': {0: 1.0, 1: 1.0, 2: 1.0, 3: 1.0, 4: 1.0, 5: 1.0}}

如需了解有关两个列的更多信息,请查看@charlesreid1

[in] OPR['ActualSalary'].astype
[out]
Name: ActualSalary, Length: 21567, dtype: object>

[in] OPR['FTE'].astype
[out]
Name: FTE, Length: 21567, dtype: float64>

我正在使用的版本: python: 3.7.3,pandas: 0.25.1在jupyter Notebook 6.0.0上。

可能是 https://dev59.com/XWYq5IYBdhLWcg3w8lNo 的重复问题。 - charlesreid1
2
这对我来说是一篇好读物,可以学到很多东西,但不幸的是,这与我在这里遇到的问题并不完全相同。还是谢谢 @charlesreid1。 - SyLviA
1
通过“构造”数据框,您是指我如何首先拥有这些数据吗?我已经从CSV文件中加载了它。ActualSalary的数据类型为:object,而FTE的数据类型为:float64。我将修改我的问题以包括这一点。 - SyLviA
3个回答

5

我相信你的ActualSalary列是字符串和整数混合的。这是我能够重现你的错误的唯一方式:

df = pd.DataFrame(
    {'ActualSalary': ['44600', '58,000.00', '70,000.00', 17550, 34693, 15674],
     'FTE': [1, 1, 1, 1, 1, 0.4]})

>>> df['ActualSalary'].str.replace(',', '').astype(float) * df['FTE']
0    44600.0
1    58000.0
2    70000.0
3        NaN
4        NaN
5        NaN
dtype: float64

问题出现在您尝试删除逗号时:
>>> df['ActualSalary'].str.replace(',', '')
0       44600
1    58000.00
2    70000.00
3         NaN
4         NaN
5         NaN
Name: ActualSalary, dtype: object

在将它们转换回浮点数之前,首先将它们转换为字符串。

fte_salary = (
    df['ActualSalary'].astype(str).str.replace(',', '')  # Remove commas in string, e.g. '55,000.00' -> '55000.00'
    .astype(float)  # Convert string column to floats.
    .mul(df['FTE'])  # Multiply by new salary column by Full-Time-Equivalent (FTE) column.
)
>>> df.assign(FTESalary=fte_salary)  # Assign new column to dataframe.
      ActualSalary  FTE  FTESalary
    0        44600  1.0    44600.0
    1    58,000.00  1.0    58000.0
    2    70,000.00  1.0    70000.0
    3        17550  1.0    17550.0
    4        34693  1.0    34693.0
    5        15674  0.4     6269.6

我之前也使用了.mul方法,但不幸的是遇到了同样的问题。 - SyLviA
@SyLviA 我无法复制你的错误。你使用的Python和Pandas版本是什么? - Alexander
Python版本:3.7.3,Pandas版本:0.25.1 我正在使用Jupyter Notebook 6.0.0 @Alexander。 - SyLviA
2
我认为问题在于ActualSalary列最初是整数和字符串的混合。首先尝试将其转换为字符串,然后按照上述方式继续,即df['ActualSalary'].astype(str).str.replace(',', '').astype(float).mul(df['FTE']) - Alexander
非常感谢@Alexander,问题已经解决了!整个过程需要将它转换为字符串,然后继续使用我的原始代码!我很高兴,但是如果它是混合的,为什么我必须首先将其转换为字符串呢?再次感谢您! - SyLviA
因为在整数上调用 str.replace() 会返回空值,所以实际上你是将 None 转换为 float 并乘以 None 和 FTE,因此得到了 NaN。你将它们全部转换为字符串,因此即使整数也是字符串,因此调用 str.replace() 将返回带有所需字符替换的字符串。 - ItIsEntropy

0

这应该可以运行:

OTR['FTESalary'] = OTR.apply(lambda x: pd.to_numeric(x['ActualSalary'].replace(",", ""), errors='coerce') * x['FTE'], axis=1)

输出

  ActualSalary  FTE  FTESalary
0        44600  1.0    44600.0
1    58,000.00  1.0    58000.0
2    70,000.00  1.0    70000.0
3        17550  1.0    17550.0
4        34693  1.0    34693.0
5        15674  0.4     6269.6

好的,我认为你需要这样做:

OTR['FTESalary'] = OTR.reset_index().apply(lambda x: pd.to_numeric(x['ActualSalary'].replace(",", ""), errors='coerce') * x['FTE'], axis=1).to_numpy().tolist() 

1
@sylvia,请问 pd.version 的输出是什么?我认为我需要安装你的版本才能看到错误信息。我不介意这样做,这样我就可以得到一个可用的版本。 - oppressionslayer
1
它是“0.25.1”(感谢您教我如何检查版本)@oppressionslayer - SyLviA
@SyLviA 好的,我添加了一个更新,请你试一下。我遇到了和你一样的错误,所以我认为我已经修复了它。实际上这不是一个 bug,而是因为我们需要重置索引,因为你已经设置了一个索引。 - oppressionslayer
我仍然遇到相同的错误:AttributeError: ("'int' object has no attribute 'replace'", 'occurred at index 20480') 这是因为我不知道如何“清理”原始的csv文件吗?@oppressionslayer - SyLviA
如果我删除reset_index,就会出现这样的错误:KeyError: ('ActualSalary','发生在索引44600处')。您能否提供数据df[0:6].to_dict()? - oppressionslayer
显示剩余2条评论

0
我能够用几个步骤完成它,但使用列表推导式可能对初学者来说不太易读。它会创建一个中间列,进行浮点数转换,因为你的 ActualSalary 列一开始是由字符串组成的。
OPR["X"] = [float(x.replace(",","")) for x in OPR["ActualSalary"]]
OPR["FTESalary"] = OPR["X"]*OPR["FTE"]

我已经使用了您上面的代码,但不幸的是,我仍然遇到了同样的问题。 - SyLviA

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接