我有一个pandas数据帧,一列是温度(人类),但是值是混合的,摄氏和华氏,我想把这个列分成两列(保留原始列)
#C Temp will be added to the end of df
df = df.join(df.Temp.apply(lambda x: np.nan if x > 43 else x))
#F Temp will be added to the end of df
df = df.join(df.Temp.apply(lambda x: np.nan if x < 43 else x))
我认为df.Temp.apply(lambda x: np.nan if x < 43 else x)
将返回一系列将加入df
的结尾,但我收到此错误
ValueError: columns overlap but no suffix specified: Index([u'Temp'], dtype='object')
答案 0 :(得分:2)
问题在于,对name
的调用中实时计算Series
的隐式join
属性也是'Temp'
,因为它是&#39 ; sa来自该列的派生计算。由于'Temp'
已存在于DataFrame中,因此它会引发异常,以表明它不知道您希望使用哪种名称更改(通过后缀)来防止名称重叠。
您可以向rsuffix
提供一个join
参数,该参数会将一个给定字符串附加到该名称,该列来自该联接的 right 操作数(在此case,函数调用中的一个)。例如:
df = df.join(df.Temp.apply(lambda x: np.nan if x > 43 else x),
rsuffix='_Celsius')
在修改后的输出DataFrame中获取名为"Temp_Celsius"
的列。还可以选择使用lsuffix
提供将附加到 left 操作数的字符串,如果您希望更改该列名称(或者您可以提供)如果您不希望任何列保留原始名称,则两者。
但请注意,在使用on
时,您总是忽略任何join
参数(加入条件) - 这意味着您默认为&#34;加入&#34;按指数。实际上,你想要的只是简单地写一个从旧列派生的新列,这使你有机会声明名称,例如:
df['Celsius'] = df.Temp.apply(lambda x: np.nan if x > 43 else x)
这是更可取的,因为它更清楚地表达了您的意图,不是为了加入而是为了创建一个列。此外,由于默认的连接方法是'left'
,如果您碰巧有重复的索引,您可能最终会为左侧索引中的每个副本多次连接,并且因为该索引与右侧相同-hand index(因此也会有重复)这可能意味着你会默默地错误地为每个连接引入更多重复项。
您也可以选择使用map
代替apply
,因为在访问专栏时,您将使用系列对象。
答案 1 :(得分:0)
我想补充一点,您可以使用where
方法更有效,更优雅地计算所需的系列:
df['Celsius'] = df.Temp.where(df.Temp > 43)
这是一个矢量化解决方案,这意味着内部循环是用C实现的。.apply
应该避免使用python循环并且速度要慢得多。此外,应尽可能避免使用lambda
函数,因为它们也会使您在多次迭代中减慢速度。熊猫作为这些问题的内置功能的负载。