我有一个数据框 df 中的一列:
Time
2 hours 3 mins
5 hours 10 mins
1 hour 40 mins
我想在df中创建一个新列'Minutes',将该列转换为分钟。
Minutes
123
310
100
有没有Python函数可以做到这一点?
你需要通过to_datetime
将其转换。
s=pd.to_datetime(df.Time.replace({'hours':'hour'},regex=True),format='%H hour %M mins')
s.dt.hour*60+s.dt.minute
Out[406]:
0 123
1 310
2 100
Name: Time, dtype: int64
我们可以使用 numpy
的 dot
和 str.findall
。
np.dot(np.array(df.Time.str.findall('\d+').tolist()).astype(int),[60,1])
Out[420]: array([123, 310, 100])
pd.eval
玩转数据分析df['Minutes'] = pd.eval(
df['Time'].replace(['hours?', 'mins'], ['*60+', ''], regex=True))
df
Time Minutes
0 2 hours 3 mins 123
1 5 hours 10 mins 310
2 1 hour 40 mins 100
这个想法是让replace
将其转换为数学表达式,然后让pandas对其进行评估:
expr = df['Time'].replace(['hours?', 'mins'], ['* 60 +', ''], regex=True)
expr
0 2 * 60 + 3
1 5 * 60 + 10
2 1 * 60 + 40
Name: Time, dtype: object
pd.eval(expr)
# array([123, 310, 100], dtype=object)
str.extract
和乘法((df['Time'].str.extract(r'(\d+) hour.*?(\d+) min').astype(int) * [60, 1])
.sum(axis=1))
0 123
1 310
2 100
dtype: int64
写一个简单的正则表达式提取数字,然后使用简单的算术运算转换为分钟。您可以将模式缩短为(df['Time'].str.extract(r'(\d+)\D*(\d+)').astype(int) * [60, 1]).sum(axis=1)
0 123
1 310
2 100
dtype: int64
根据 @Quang Hoang 的建议。有没有一个Python函数可以做到这一点?
只有在你自己编写一个之后才有。
def to_minutes(time_string):
hours, _, minutes, _ = time_string.split(' ')
return int(hours) * 60 + int(minutes)
结果应该类似于:
>>> to_minutes('2 hours 3 mins')
123
我相信你可以将其转换为timedelta
并强制转换为timedelta64[m]
:
pd.to_timedelta(df.Time.str.replace('mins', 'm'), unit='m').astype('timedelta64[m]')
Out[786]:
0 123.0
1 310.0
2 100.0
Name: Time, dtype: float64
如果你喜欢lambda函数,你也可以使用:
df.Time.apply(lambda x: sum(np.array([ int(i) for i in re.match(r'(\d+) hour[s]? (\d+) min[s]?', x).groups()]) * [60, 1]))
def Mins(row):
return int(row['Time'].split(' ')[0])*60 + int(row['Time'].split(' ')[2])
df.apply(Mins,axis=1)
我认为没有内置函数,但是你可以自己构建一个函数,然后在pandas中使用.apply()方法。
这可能不是最简短的答案,但它将让你了解如何在Pandas中使用基本的Python函数。我认为这非常有帮助!
我构建的函数:
import re
def calculate_number_of_minutes(hours_string):
regex = '\d+( )\w+'
// I build a regex which can find a sequence of digits and a single word
result = re.finditer(regex, text, re.DOTALL)
// I find such patterns in the given string
minutes = 0
for element in result:
fragment = element.group()
if 'hour' in fragment:
minutes += int(re.search('\d+', fragment).group()) * 60
// if there are 'hours', the associated number is multiplied by 60
// and added to the count
else:
minutes += int(re.search('\d+', fragment).group())
return minutes
text = '5 hours 10 mins'
print(calculate_number_of_minutes(text))
data.loc[;, 'Time'] = data['Time'].apply(lambda x: calculate_number_of_minutes(x))
'(\d+)\D*(\d+)'
。 - Quang Hoang