问题描述
我有一个用 Pandas 提取的数据框,其中一个列看起来像这样:
我想要做的是提取此列中的数值(浮点数),这本身我可以做到。问题出现是因为我有一些单元格,例如图像中的单元格 20,其中有多个数字,因此我想对这些值求平均值。我认为为此我首先需要识别字符串中不同的数值组(每个浮点数),然后将它们提取为浮点数,然后对它们进行操作。我不知道该怎么做。
编辑:我使用正则表达式中的 re.findall 命令找到了解决方案。这是基于此主题 Find all floats or ints in a given string 中的一个问题的答案。
for index,value in z.iteritems():
z[index]=statistics.mean([float(h) for h in re.findall(r'(?:\b\d{1,2}\b(?:\.\d*))',value)])
请注意,由于我拥有的数据类型,我没有包括整数匹配,并且只考虑了最多 99 的值。
但是,由于循环的原因,我使用这种方法收到了警告(仅对系列中的一个元素执行此操作时没有警告):
SettingWithcopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
虽然我的数据没有出现任何问题,但此警告重要吗?
解决方法
我认为您可以从这里的 Pandas 向量化操作中受益。在原始数据帧上使用 findall
并按顺序应用 pd.Series
从列表转换为列和 pd.to_numeric
从字符串转换为数字类型(默认返回 dtype 为 float64
) .然后用 .mean(axis=1)
计算每行值的平均值。
import pandas as pd
d = {0: {0: '2.469 (VLT: emission host)',1: '1.942 (VLT: absorption)',2: '1.1715 (VLT: absorption)',3: '0.42 (NOT: absorption)|0.4245 (GTC)|0.4250 (ESO-VLT UT2: absorption & emission)',4: '3.3765 (VLT: absorption)',5: '1.86 (Xinglong: absorption)| 1.86 (GMG: absorption)|1.859 (VLT: absorption)',6: '<2.4 (NOT: inferred)'}}
df = pd.DataFrame(d)
print(df)
s_mean = df[0].str.findall(r'(?:\b\d{1,2}\b(?:\.\d*))')\
.apply(pd.Series)\
.apply(pd.to_numeric)\
.mean(axis=1)
print(s_mean)
s_mean的输出
0 2.469000
1 1.942000
2 1.171500
3 0.423167
4 3.376500
5 1.859667
6 2.400000
,
根据我之前在原始帖子的编辑中所写的内容,我找到了一个解决方案:
它包括使用带有 regex 的 re.findall()
命令,如该线程 Find all floats or ints in a given string 中发布的:
statistics.mean([float(h) for h in re.findall(r'(?:\b\d{1,2}\b(?:\.\d*))',string)])
然后,要循环在数据帧列上,只需将 lambda x: 方法与 pandas apply 命令({{3} })。为此,我定义了一个执行上述操作的函数 (redshift_to_num),然后将此函数应用于数据帧列中的每个元素:
import re
import pandas as pd
import statistics
def redshift_to_num(string):
measures=[float(h) for h in re.findall(r'(?:\b\d{1,string)]
mean=statistics.mean(measures)
return mean
df.Redshift=df.Redshift.apply(lambda x: redshift_to_num(x))
注意事项:
- 我感兴趣的数据存储在数据框列
df.Redshift
中。 - 在
re.findall
命令中,由于我拥有的数据类型,我没有包含整数匹配,并且只考虑了最多 99 的值。