Pandas - 从 Pandas 的同一个字符串中选择几个浮点数来操作它们

问题描述

我有一个用 Pandas 提取的数据框,其中一个列看起来像这样:

Image: A few elements of the column of interest of the Dataframe

我想要做的是提取此列中的数值(浮点数),这本身我可以做到。问题出现是因为我有一些单元格,例如图像中的单元格 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
,

根据我之前在原始帖子的编辑中所写的内容,我找到了一个解决方案:

它包括使用带有 regexre.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 的值。