【问题标题】:Calculating averaged data in and writing to csv from a pandas dataframe从 pandas 数据帧计算平均数据并写入 csv
【发布时间】:2021-11-16 07:45:34
【问题描述】:

我有一个非常大的空间数据集存储在数据框中。我将该数据帧的一部分放入一个新的较小子集中以运行进一步的计算。 数据具有 x、y 和 z 坐标以及许多附加列,其中一些是文本,一些是数字。 x 和 y 坐标位于定义的网格上,并且具有已知的间距。 数据看起来像这样

x,y,z,text1,text2,text3,float1,float2
75000,45000,120,aa,bbb,ii,12,0.2
75000,45000,110,bb,bbb,jj,22,0.9
75000,45100,120,aa,bbb,ii,11,1.8
75000,45100,110,bb,bbb,jj,45,2.4
75000,45100,100,bb,ccc,ii,13.6,1
75100,45000,120,bb,ddd,jj,8.2,2.1
75100,45000,110,bb,ddd,ii,12,0.6

对于每个 x 和 y 对,我想遍历两个系列的文本值并在 z 方向上做三件事。

  1. 计算具有第三个特定文本值的所有值的一个数值的平均值
  2. 将具有相同文本值的所有值的另一个数值相加
  3. 将 'x, y, average, sum' 的结果表写入 csv。

我的代码执行第三部分(尽管速度很慢),但没有计算 1 或 2,或者至少我似乎没有在输出中得到平均值和总和计算。

我做错了什么,如何加快速度?

    for text1 in text_list1:
        for text2 in text_list2:
            # Get the data into smaller dataframe
            df = data.loc[ (data["textfield1"] == text1) & (data["textfield2"] == text2 ) ]
                
            #Get the minimum and maximum x and y 
            minXw = df['x'].min()
            maxXw = df['x'].max()
            minYw = df['y'].min()
            maxYw = df['y'].max()
            
            # dictionary for quicker printing
            dict_out  = {}
            rows_list = []
            
            # Make output filename
            filenameOut = text1+"_"+text2+"_Values.csv"
            # Start looping through x values
            for x in np.arange(minXw, maxXw, x_inc):
                xcount += 1
                # Start looping through y values
                for y in np.arange(minYw, maxYw, y_inc):
                    ycount += 1
                    
                    # calculate average and sum
                    ave_val = df.loc[df['textfield3'] == 'text3', 'float1'].mean()
                    sum_val = df.loc[df['textfield3'] == 'text3', 'float2'].sum()

                    # Make Dictionary of output values
                    dict_out  = dict([('text1', text1), 
                                      ('text2', text2), 
                                      ('text3', df['text3']),
                                      ('x'    , x-x_inc),
                                      ('y'    , y-y_inc),
                                      ('ave'  , ave_val),
                                      ('sum'   , sum_val)])
                    rows_list_c.append(dict_out)

            # Write csv      
            columns = ['text1','text2','text3','x','y','ave','sum']
            with open(filenameOut, 'w') as csvfile:
                writer = csv.DictWriter(csvfile, fieldnames=columns)
                writer.writeheader()
                for data in dict_out:
                    writer.writerow(data)

我生成的 csv 给了我:

text1,text2,text3,x,y,ave,sum

text1,text2,,74737.5,43887.5,nan,0.0
text1,text2,,74737.5,43912.5,nan,0.0
text1,text2,,74737.5,43937.5,nan,0.0
text1,text2,,74737.5,43962.5,nan,0.0

【问题讨论】:

  • 显示示例输入数据和预期输出会很有帮助。您的平均值和总和将是 textfield3 的每个值的汇总度量,那么如何在同一个输出表中显示 x、y 和 z?
  • 对不起,我应该更清楚。 Z 在输出中不是必需的,x 和 y 可以从循环中获取。这些位的工作方式如当前输出所示。我的输出中似乎没有填充 ave 和 sum 值和文本。尝试从数据框中提取哪些值
  • 看起来可能没有(data["textfield1"] == text1) & (data["textfield2"] == text2 )df['textfield3'] == 'text3' 的情况 - 列名或值是否可能不正确?您能否尝试显示与您给出的示例输入一致的代码,包括text_list1text_list2 中的内容?
  • 我会检查真实的输入数据,但我确信所有三个文本值都存在。如果我错了,你刚刚解决了我的问题:)。
  • 似乎还有其他问题 - 您正在循环通过 xy 但平均值和总和每次都相同(对于 text1text2 的每个值) .这也是它变慢的原因——取决于x_incy_inc,您重复相同的操作很多次。查看groupbyagg

标签: python pandas dataframe average export-to-csv


【解决方案1】:

不太清楚你想做什么。但这是一个起点

如果您只需要处理具有特定 text3value 的行,请先过滤掉其他行:

df = df[df.text3=="my_value"]

如果此时你不再需要 text3,你也可以放弃它

df = df.drop(columns="text3")

然后您处理几个子数据帧,并将它们中的每一个写入自己的 csv 文件。 groupby 是完美的工具:

for (text1, text2), sub_df in df.groupby(["text1", "text2"]):
    filenameOut = text1+"_"+text2+"_Values.csv"
    # Process sub df
    output_df = process(sub_df)
    # Write sub df
    output_df.to_csv(filenameOut)

请注意,如果您将数据保留为 DataFrame 而不是将其转换为 dict,则可以使用 DataFrame to_csv 方法来简单地编写输出 csv。

现在让我们看一下 process 函数(注意,您实际上不需要将其设置为单独的函数,您也可以将函数体转储到 for 循环中)。

此时,如果我理解正确,您想要计算具有相同 x 和 y 坐标的每一行的总和和平均值。在这里,您可以再次使用groupbyagg 函数来计算组的平均值和总和。

def process(sub_df):
   # drop the text1 and text2 columns since they are in the filename anyway
   out = sub_df.drop(columns=["text1","text2"])
   
   # Compute mean and max
   return out.groupby(["x", "y"]).agg(ave=("float1", "mean"), sum=("float2", "sum"))

就是这样。

奖励:2 线版本(但不要那样做...)

for (text1, text2), sub_df in df[df.text3=="my_value"].drop(columns="text3").groupby(["text1", "text2"]):
    sub_df.drop(columns=["text1","text2"]).groupby(["x", "y"]).agg(ave=("float1", "mean"), sum=("float2", "sum")).to_csv(text1+"_"+text2+"_Values.csv")

【讨论】:

    【解决方案2】:

    要在 pandas 中高效地执行此操作,您需要使用 groupbyagg 和内置的 to_csv 方法,而不是使用 for 循环来构造数据列表并使用csv 模块。像这样的:

    groups = data[data["text1"].isin(text_list1) & data["text2"].isin(text_list2)] \
        .groupby(["text1", "text2"])
    
    for (text1, text2), group in groups:
        group.groupby("text3") \
            .agg({"float1": np.mean, "float2": sum}) \
            .to_csv(f"{text1}_{text2}_Values.csv")
    

    目前尚不清楚您要对xy 值的递增做什么,这也是使您当前的代码非常慢的原因。要按xy 的间隔显示浮点列的总和和平均值,您也可以制作 bin 列并按这些列分组。

    data["x_bin"] = (data["x"] - data["x"].min()) // x_inc
    data["y_bin"] = (data["y"] - data["y"].min()) // y_inc
    groups = data[data["text1"].isin(text_list1) & data["text2"].isin(text_list2)] \
        .groupby(["text1", "text2"])
    
    for (text1, text2), group in groups:
        group.groupby(["text3", "x_bin", "y_bin"]) \
            .agg({"x": "first", "y": "first", "float1": np.mean, "float2": sum}) \
            .to_csv(f"{text1}_{text2}_Values.csv")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-03
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 2018-09-17
      • 1970-01-01
      相关资源
      最近更新 更多