使用 Pandas 数据帧减法和索引

Working with Pandas Dataframe Subtraction and Indexes

我有几个文本文件,其中包含一些关于房地产数据随时间变化的时间顺序指标。我想将此数据导入数据框,然后计算一个新的数据框,该数据框是特定城市的指标与该日期所有城市的平均值之间的差异。对于给定的日期,如果个别城市没有数据,我也希望输出为 NaN,即使其他城市有相关的平均值。

我遇到或担心的几个问题

--> 我不确定最好的方法是如何避免某些孟菲斯数据 = 'NaN' 的情况,但多个城市的平均值为 17,因此孟菲斯 - 平均值 = -17。我想要的行为是孟菲斯 (NaN) 减去平均值 (17) = NaN。

--> 在从各个城市中减去我的平均值时,我的列顺序变为字母顺序,我不知道为什么。虽然我手动检查过,但我担心我在索引方面做错了什么,所以我可能在不知情的情况下减去未对齐的列或行。

--> 我正在从我的原始数据集中提取一些文本数据(一个 'Record' 字符串和 'City' 名称),并将其连接回最终确定的相关城市。这似乎有点低效,同样,我担心这可能会增加索引风险。

import glob
import pandas as pd

df = pd.concat([pd.read_csv(f, na_values = ['#VALUE!', '#DIV/0!'], keep_default_na = True) for f in glob.glob('city Text Files/*.txt')], ignore_index = True)

df_headers = df.loc[:,['Record','City']]
df_average = df.groupby(['Date'], as_index=False).mean()

df_rel_cities_wip = (df.set_index('Date')-df_average.set_index('Date').reindex(df.Date)).reset_index()
df_rel_cities_wip = df_rel_cities_wip.drop(['Record','City'], axis = 1) #these otherwise stay behind as blank columns because they're strings
df_rel_cities_wip = df_rel_cities_wip.round(6) #Gets rid of floating point almost-zeros
df_rel_cities = pd.concat([df_headers, df_rel_cities_wip], axis=1, sort=False) #Bolts city names and alpha record numbers back to the relative dataset

编辑 - 添加一些示例数据以进行说明 第一个数据框 (df) 将是原始记录。由于各种原因,1 月 3 日孟菲斯可能无法提供可行的 $/sqft 或上市天数 (DOM)。

Record  City    Date        $/SQFT  DOM
M12 Memphis 01/01/2018  100 18
M13 Memphis 01/02/2018  112 73
M14 Memphis 01/03/2018  NaN NaN
D73 Dallas  01/01/2018  300 36
D74 Dallas  01/02/2018  320 53
D75 Dallas  01/03/2018  325 43
A19 Atlanta 01/01/2018  255 11
A20 Atlanta 01/03/2018  263 18

所有这些城市每天的平均指标如下 (df_average)

Date        $/SQFT  DOM
01/01/2018  218.3   21.7
01/02/2018  216.0   63.0
01/03/2018  294.0   30.5

我的最终数据框 (df_rel_cities) 将显示每个日期的 'city average' 与实际日期之间的差异。请注意,M14 孟菲斯一开始是 NaN - 因此,考虑到孟菲斯当天的数据有问题,因此期望的结果是将 NaN 视为与行业的差异。当我 运行 我上面的代码时,我发现它也按字母顺序排列了我的列顺序。

Record  City    Date        $/SQFT  DOM
M12 Memphis 01/01/2018  -118.3  -3.7
M13 Memphis 01/02/2018  -104.0  10.0
M14 Memphis 01/03/2018  NaN NaN
D73 Dallas  01/01/2018  81.7    14.3
D74 Dallas  01/02/2018  104.0   -10.0
D75 Dallas  01/03/2018  31.0    12.5
A19 Atlanta 01/01/2018  36.7    -10.7
A20 Atlanta 01/03/2018  -31.0   -12.5

我认为需要:

df = pd.concat([pd.read_csv(f, na_values = ['#VALUE!', '#DIV/0!'], keep_default_na = True) 
                for f in glob.glob('city Text Files/*.txt')])

#get only numeric columns
cols = df.select_dtypes(np.number).columns

#create DataFrame with same size as original with means
df_average = df.groupby('Date')[cols].transform('mean')
print (df_average)
       $/SQFT        DOM
0  218.333333  21.666667
1  216.000000  63.000000
2  294.000000  30.500000
3  218.333333  21.666667
4  216.000000  63.000000
5  294.000000  30.500000
6  218.333333  21.666667
7  294.000000  30.500000

#substract only numeric columns 
df[cols] = (df[cols] - df_average ).round(1)
print (df)
  Record     City        Date  $/SQFT   DOM
0    M12  Memphis  01/01/2018  -118.3  -3.7
1    M13  Memphis  01/02/2018  -104.0  10.0
2    M14  Memphis  01/03/2018     NaN   NaN
3    D73   Dallas  01/01/2018    81.7  14.3
4    D74   Dallas  01/02/2018   104.0 -10.0
5    D75   Dallas  01/03/2018    31.0  12.5
6    A19  Atlanta  01/01/2018    36.7 -10.7
7    A20  Atlanta  01/03/2018   -31.0 -12.5