计算 pandas 数据帧中的平均数据并写入 csv
Calculating averaged data in and writing to csv from a pandas dataframe
我有一个非常大的空间数据集存储在数据框中。我正在将该数据帧的一部分放入一个新的更小的子集中,以 运行 进一步计算。
数据具有 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 方向上做三件事。
- 计算具有第三个特定文本值的所有值的一个数值的平均值
- 对具有相同文本值的所有值求和另一个数值
- 将 'x, y, average, sum' 的结果 table 写入 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
要在 pandas 中以有效的方式执行此操作,您将需要使用 groupby
、agg
和内置的 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")
目前尚不清楚您尝试对 x
和 y
值进行递增的目的,这也是您当前代码非常慢的原因。要按 x
和 y
的间隔显示浮点列的总和和平均值,您也可以创建 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")
不太清楚您要做什么。但这里是一个起点
如果您只需要处理具有特定 text3
值的行,请先过滤掉其他行:
df = df[df.text3=="my_value"]
如果此时你不再需要text3,你也可以drop它
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 而不是将其转换为字典,则可以使用 DataFrame to_csv
方法简单地写入输出 csv。
现在让我们看一下process函数(注意你真的不需要把它做成一个单独的函数,你也可以把函数体放到for循环里)。
此时,如果我没理解错的话,您想计算具有相同 x 和 y 坐标的每一行的总和和平均值。在这里您可以再次使用 groupby
和 agg
函数来计算组的均值和总和。
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")
我有一个非常大的空间数据集存储在数据框中。我正在将该数据帧的一部分放入一个新的更小的子集中,以 运行 进一步计算。 数据具有 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 方向上做三件事。
- 计算具有第三个特定文本值的所有值的一个数值的平均值
- 对具有相同文本值的所有值求和另一个数值
- 将 'x, y, average, sum' 的结果 table 写入 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
要在 pandas 中以有效的方式执行此操作,您将需要使用 groupby
、agg
和内置的 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")
目前尚不清楚您尝试对 x
和 y
值进行递增的目的,这也是您当前代码非常慢的原因。要按 x
和 y
的间隔显示浮点列的总和和平均值,您也可以创建 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")
不太清楚您要做什么。但这里是一个起点
如果您只需要处理具有特定 text3
值的行,请先过滤掉其他行:
df = df[df.text3=="my_value"]
如果此时你不再需要text3,你也可以drop它
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 而不是将其转换为字典,则可以使用 DataFrame to_csv
方法简单地写入输出 csv。
现在让我们看一下process函数(注意你真的不需要把它做成一个单独的函数,你也可以把函数体放到for循环里)。
此时,如果我没理解错的话,您想计算具有相同 x 和 y 坐标的每一行的总和和平均值。在这里您可以再次使用 groupby
和 agg
函数来计算组的均值和总和。
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")