Python Pandas中的.apply()函数索引错误

3

我有以下DataFrame:

                              P     N  ID  Year  Month
TS                                                    
2016-06-26 19:30:00  263.600006   5.4   5  2016      6
2016-06-26 20:00:00  404.700012   5.6   5  2016      6
2016-06-26 21:10:00  438.600006   6.0   5  2016      6
2016-06-26 21:20:00  218.600006   5.6   5  2016      6
2016-07-02 16:10:00  285.300049  15.1   5  2016      7

我正在尝试根据列 YearMonth 的值添加新的列,类似于以下内容:

def exp_records(row):
    return calendar.monthrange(row['Year'], row['Month'])[1]
df['exp_counts'] = df.apply(exp_records, axis=1)

但是我遇到了以下错误:
TypeError: ('integer argument expected, got float', 'occurred at index 2016-06-26 19:30:00')
如果我使用reset_index()将其重置为整数,则上述.apply()函数可以正常工作。这是预期的行为吗?
我正在使用Python 3.4和pandas 0.19.1。

重新创建DataFrame的代码:

s = '''
TS,P,N,ID,Year,Month
2016-06-26 19:30:00,263.600006,5.4,5,2016,6
2016-06-26 20:00:00,404.700012,5.6,5,2016,6
2016-06-26 21:10:00,438.600006,6.0,5,2016,6
2016-06-26 21:20:00,218.600006,5.6,5,2016,6
2016-07-02 16:10:00,285.300049,15.1,5,2016,7
'''

df = pd.read_csv(pd.compat.StringIO(s), index_col=0, parse_dates=True)

有趣的是,当索引为日期时间类型时,lociloc等返回浮点数,即使列类型为整数也是如此。这可能是一个bug。您可以将row['Year']更改为int(row['Year'])作为解决方法(当然,月份也是一样)。或者您可以轻松地使用df.index.days_in_month - ayhan
1
@ayhan:另外,当我使用所有int数据类型测试给定的数据集时,它返回了适当的值。但是,当其中一个更改为float时,它强制将所有列转换为浮点类型(即使提供reduce=False也没有帮助)。这就是为什么它要求以int作为输入的原因。此外,这不仅适用于datetime,即整数索引也显示类似的行为。 - Nickil Maveli
@NickilMaveli 是的,我也在尝试使用浮点索引,并且我发现当DataFrames具有不同数据类型的列时会出现相同的问题。 - ayhan
1个回答

5

解决方案

使用df[['Year', 'Month']]进行应用:

df['exp_counts'] = df[['Year', 'Month']].apply(exp_records, axis=1)

结果:

                              P     N  ID  Year  Month  exp_counts
TS                                                                
2016-06-26 19:30:00  263.600006   5.4   5  2016      6          30
2016-06-26 20:00:00  404.700012   5.6   5  2016      6          30
2016-06-26 21:10:00  438.600006   6.0   5  2016      6          30
2016-06-26 21:20:00  218.600006   5.6   5  2016      6          30
2016-07-02 16:10:00  285.300049  15.1   5  2016      7          31

原因

尽管您的年份月份列是整数类型:

df.info()

<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 5 entries, 2016-06-26 19:30:00 to 2016-07-02 16:10:00
Data columns (total 5 columns):
P        5 non-null float64
N        5 non-null float64
ID       5 non-null int64
Year     5 non-null int64
Month    5 non-null int64
dtypes: float64(2), int64(3)
memory usage: 240.0 bytes

你通过按行访问它们,这使它们成为浮动元素:

df.T.info()

<class 'pandas.core.frame.DataFrame'>
Index: 5 entries, P to Month
Data columns (total 5 columns):
2016-06-26 19:30:00    5 non-null float64
2016-06-26 20:00:00    5 non-null float64
2016-06-26 21:10:00    5 non-null float64
2016-06-26 21:20:00    5 non-null float64
2016-07-02 16:10:00    5 non-null float64
dtypes: float64(5)
memory usage: 240.0+ bytes

自从df.apply(exp_records, axis=1)按行运行后,你将基本上转换为行。
这是exp_recordsrow的内容:
P         263.600006
N           5.400000
ID          5.000000
Year     2016.000000
Month       6.000000
Name: 2016-06-26T19:30:00.000000000, dtype: float64

只创建一个包含列YearMonth的数据框时,会将两个列转换为浮点数,因为它们都是整数:

df[['Year', 'Month']].T.info()

<class 'pandas.core.frame.DataFrame'>
Index: 2 entries, Year to Month
Data columns (total 5 columns):
2016-06-26 19:30:00    2 non-null int64
2016-06-26 20:00:00    2 non-null int64
2016-06-26 21:10:00    2 non-null int64
2016-06-26 21:20:00    2 non-null int64
2016-07-02 16:10:00    2 non-null int64
dtypes: int64(5)
memory usage: 96.0+ bytes

谢谢您的解释,这解决了我的问题。@ayhan提出的解决方案速度显著更快,但进一步调查总是好的。 - ardms

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