Pandas- 在两个不共享索引的数据帧之间屏蔽 rows/columns
Pandas- masking rows/columns between two dataframes where indexes are not shared
问题
我有两个数据集,比方说,它们描述了海洋在特定深度和特定纬度的温度。数据集来自两个不同的模型,因此具有不同的分辨率,模型 1 的纬度分辨率更高,两个模型的深度维度级别不同。我已将两个数据集都转换为 pandas 数据帧,其中深度作为垂直索引,纬度作为列标签。我想屏蔽掉两个数据帧之间不共享的行(深度)和列(纬度),因为我会有所不同并且不想插入数据。我找到了如何屏蔽掉行和列中的某些值,但我想屏蔽掉整个行和列。
我在深度上使用 np.intersect1d 作为列表来查找模型之间不共享的深度,并且我使用条件语句创建了一个布尔列表,该语句为每个索引显示 True,其中的值是唯一的数据框。但是,我不确定如何使用它作为面具,或者即使我可以。 DataFrame.mask 表示“条件数组必须与自身形状相同”,但条件数组是一维的,而数据框是二维的。我不确定如何仅引用数据帧的索引来应用掩码。我觉得我走在正确的轨道上,但我不完全确定,因为我还是 pandas 的新手。 (我曾尝试搜索类似的问题,但 none 与我所看到的完全匹配。)
代码(简化的工作示例)
注意-这是在 Jupyter notebook 环境中编写的
import numpy as np
import pandas as pd
# Model 1 data
depthmod1 = [5, 10, 15, 20, 30, 50, 60, 80, 100] #depth in meters
latmod1 = [50, 50.5, 51, 51.5, 52, 52.5, 53] #latitude in degrees north
tmpumod1 = np.random.randint(273,303,size=(len(depthmod1),len(latmod1))) #temperature
dfmod1 = pd.DataFrame(tmpumod1,index=depthmod1,columns=latmod1)
print(dfmod1)
50.0 50.5 51.0 51.5 52.0 52.5 53.0
5 299 300 300 293 285 293 273
10 273 288 293 292 290 302 273
15 277 279 284 302 280 294 284
20 291 295 277 276 295 279 274
30 281 284 284 275 295 284 282
50 284 276 291 282 286 295 295
60 298 294 289 294 285 289 288
80 285 284 275 298 287 277 300
100 292 295 294 273 291 276 290
# Model 2 data
depthmod2 = [5, 10, 15, 25, 35, 50, 60, 100]
latmod2 = [50, 51, 52, 53]
tmpumod2 = np.random.randint(273,303,size=(len(depthmod2), len(latmod2)))
dfmod2 = pd.DataFrame(tmpumod2,index=depthmod2,columns=latmod2)
print(dfmod2)
50 51 52 53
5 297 282 275 292
10 298 286 292 282
15 286 285 288 273
25 292 288 279 299
35 301 295 300 288
50 277 301 281 277
60 276 293 295 297
100 275 279 292 287
# Find shared depths
depthxsect = np.intersect1d(depthmod1, depthmod2)
print(depthxsect, depthxsect.shape)
Shared depths: [ 5 10 15 50 60 100] (6,)
# Boolean mask for model 1
depthmask = dfmod1.index.isin(depthxsect) == False
print("Bool showing where mod1 index is NOT in mod2: ", depthmask)
Bool showing where mod1 index is NOT in mod2: [False False False True True False False True False]
# Mask data
dfmod1masked = dfmod1.mask(depthmask1,np.nan)
print(dfmod1masked)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-14-fedf013c2200> in <module>
----> 1 dfmod1masked = dfmod1.mask(depthmask1,np.nan)
2 print(dfmod1masked)
[...]
ValueError: Array conditional must be same shape as self
问题
如何按索引屏蔽行,以便我只剩下 rows/indexes [ 5 10 15 50 60 100] 可用于两个数据帧?我将对列(纬度)进行类似的屏蔽,因此希望行的解决方案也适用于列。我也不想合并数据框。它们应该保持独立,除非为此需要合并。
depthxsect
return 是您需要的 np.array
个索引。因此,您可以跳过创建布尔数组 depthmask
,只需使用 .loc
将 np.array 传递给您的 datframe。如果您试图 保留 所有行,但仅保留 return NaN
其他索引上的值,则应使用 .mask
。
获得dfmod1
和depthxsect
后,您可以简单地使用:
dfmod1.loc[depthxsect]
完整的可重现代码:
import pandas as pd
import numpy as np
# Model 1 data
depthmod1 = [5, 10, 15, 20, 30, 50, 60, 80, 100] #depth in meters
latmod1 = [50, 50.5, 51, 51.5, 52, 52.5, 53] #latitude in degrees north
tmpumod1 = np.random.randint(273,303,size=(len(depthmod1),len(latmod1))) #temperature
dfmod1 = pd.DataFrame(tmpumod1,index=depthmod1,columns=latmod1)
depthmod2 = [5, 10, 15, 25, 35, 50, 60, 100]
latmod2 = [50, 51, 52, 53]
tmpumod2 = np.random.randint(273,303,size=(len(depthmod2), len(latmod2)))
dfmod2 = pd.DataFrame(tmpumod2,index=depthmod2,columns=latmod2)
depthxsect = np.intersect1d(depthmod1, depthmod2)
dfmod1.loc[depthxsect]
Out[2]:
50.0 50.5 51.0 51.5 52.0 52.5 53.0
5 284 291 280 287 297 286 277
10 294 279 302 283 284 298 291
15 278 296 286 298 279 275 286
50 284 281 297 290 302 299 280
60 290 301 302 298 283 286 287
100 285 283 297 287 289 282 283
我也包含了您正在尝试的方法。您必须在列上指定 mask
。您在整个数据帧上执行此操作:
import pandas as pd
import numpy as np
# Model 1 data
depthmod1 = [5, 10, 15, 20, 30, 50, 60, 80, 100] #depth in meters
latmod1 = [50, 50.5, 51, 51.5, 52, 52.5, 53] #latitude in degrees north
tmpumod1 = np.random.randint(273,303,size=(len(depthmod1),len(latmod1))) #temperature
dfmod1 = pd.DataFrame(tmpumod1,index=depthmod1,columns=latmod1)
dfmod1
depthmod2 = [5, 10, 15, 25, 35, 50, 60, 100]
latmod2 = [50, 51, 52, 53]
tmpumod2 = np.random.randint(273,303,size=(len(depthmod2), len(latmod2)))
dfmod2 = pd.DataFrame(tmpumod2,index=depthmod2,columns=latmod2)
depthxsect = np.intersect1d(depthmod1, depthmod2)
depthmask = dfmod1.index.isin(depthxsect) == False
for col in dfmod1.columns:
dfmod1[col] = dfmod1[col].mask(depthmask, np.nan)
dfmod1
Out[3]:
50.0 50.5 51.0 51.5 52.0 52.5 53.0
5 289.0 274.0 297.0 274.0 277.0 278.0 277.0
10 282.0 280.0 277.0 302.0 297.0 289.0 278.0
15 300.0 282.0 297.0 297.0 300.0 279.0 291.0
20 NaN NaN NaN NaN NaN NaN NaN
30 NaN NaN NaN NaN NaN NaN NaN
50 285.0 297.0 292.0 301.0 296.0 289.0 291.0
60 295.0 299.0 278.0 295.0 299.0 293.0 277.0
80 NaN NaN NaN NaN NaN NaN NaN
100 292.0 293.0 289.0 291.0 289.0 276.0 286.0
问题
我有两个数据集,比方说,它们描述了海洋在特定深度和特定纬度的温度。数据集来自两个不同的模型,因此具有不同的分辨率,模型 1 的纬度分辨率更高,两个模型的深度维度级别不同。我已将两个数据集都转换为 pandas 数据帧,其中深度作为垂直索引,纬度作为列标签。我想屏蔽掉两个数据帧之间不共享的行(深度)和列(纬度),因为我会有所不同并且不想插入数据。我找到了如何屏蔽掉行和列中的某些值,但我想屏蔽掉整个行和列。
我在深度上使用 np.intersect1d 作为列表来查找模型之间不共享的深度,并且我使用条件语句创建了一个布尔列表,该语句为每个索引显示 True,其中的值是唯一的数据框。但是,我不确定如何使用它作为面具,或者即使我可以。 DataFrame.mask 表示“条件数组必须与自身形状相同”,但条件数组是一维的,而数据框是二维的。我不确定如何仅引用数据帧的索引来应用掩码。我觉得我走在正确的轨道上,但我不完全确定,因为我还是 pandas 的新手。 (我曾尝试搜索类似的问题,但 none 与我所看到的完全匹配。)
代码(简化的工作示例)
注意-这是在 Jupyter notebook 环境中编写的
import numpy as np
import pandas as pd
# Model 1 data
depthmod1 = [5, 10, 15, 20, 30, 50, 60, 80, 100] #depth in meters
latmod1 = [50, 50.5, 51, 51.5, 52, 52.5, 53] #latitude in degrees north
tmpumod1 = np.random.randint(273,303,size=(len(depthmod1),len(latmod1))) #temperature
dfmod1 = pd.DataFrame(tmpumod1,index=depthmod1,columns=latmod1)
print(dfmod1)
50.0 50.5 51.0 51.5 52.0 52.5 53.0
5 299 300 300 293 285 293 273
10 273 288 293 292 290 302 273
15 277 279 284 302 280 294 284
20 291 295 277 276 295 279 274
30 281 284 284 275 295 284 282
50 284 276 291 282 286 295 295
60 298 294 289 294 285 289 288
80 285 284 275 298 287 277 300
100 292 295 294 273 291 276 290
# Model 2 data
depthmod2 = [5, 10, 15, 25, 35, 50, 60, 100]
latmod2 = [50, 51, 52, 53]
tmpumod2 = np.random.randint(273,303,size=(len(depthmod2), len(latmod2)))
dfmod2 = pd.DataFrame(tmpumod2,index=depthmod2,columns=latmod2)
print(dfmod2)
50 51 52 53
5 297 282 275 292
10 298 286 292 282
15 286 285 288 273
25 292 288 279 299
35 301 295 300 288
50 277 301 281 277
60 276 293 295 297
100 275 279 292 287
# Find shared depths
depthxsect = np.intersect1d(depthmod1, depthmod2)
print(depthxsect, depthxsect.shape)
Shared depths: [ 5 10 15 50 60 100] (6,)
# Boolean mask for model 1
depthmask = dfmod1.index.isin(depthxsect) == False
print("Bool showing where mod1 index is NOT in mod2: ", depthmask)
Bool showing where mod1 index is NOT in mod2: [False False False True True False False True False]
# Mask data
dfmod1masked = dfmod1.mask(depthmask1,np.nan)
print(dfmod1masked)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-14-fedf013c2200> in <module>
----> 1 dfmod1masked = dfmod1.mask(depthmask1,np.nan)
2 print(dfmod1masked)
[...]
ValueError: Array conditional must be same shape as self
问题
如何按索引屏蔽行,以便我只剩下 rows/indexes [ 5 10 15 50 60 100] 可用于两个数据帧?我将对列(纬度)进行类似的屏蔽,因此希望行的解决方案也适用于列。我也不想合并数据框。它们应该保持独立,除非为此需要合并。
depthxsect
return 是您需要的 np.array
个索引。因此,您可以跳过创建布尔数组 depthmask
,只需使用 .loc
将 np.array 传递给您的 datframe。如果您试图 保留 所有行,但仅保留 return NaN
其他索引上的值,则应使用 .mask
。
获得dfmod1
和depthxsect
后,您可以简单地使用:
dfmod1.loc[depthxsect]
完整的可重现代码:
import pandas as pd
import numpy as np
# Model 1 data
depthmod1 = [5, 10, 15, 20, 30, 50, 60, 80, 100] #depth in meters
latmod1 = [50, 50.5, 51, 51.5, 52, 52.5, 53] #latitude in degrees north
tmpumod1 = np.random.randint(273,303,size=(len(depthmod1),len(latmod1))) #temperature
dfmod1 = pd.DataFrame(tmpumod1,index=depthmod1,columns=latmod1)
depthmod2 = [5, 10, 15, 25, 35, 50, 60, 100]
latmod2 = [50, 51, 52, 53]
tmpumod2 = np.random.randint(273,303,size=(len(depthmod2), len(latmod2)))
dfmod2 = pd.DataFrame(tmpumod2,index=depthmod2,columns=latmod2)
depthxsect = np.intersect1d(depthmod1, depthmod2)
dfmod1.loc[depthxsect]
Out[2]:
50.0 50.5 51.0 51.5 52.0 52.5 53.0
5 284 291 280 287 297 286 277
10 294 279 302 283 284 298 291
15 278 296 286 298 279 275 286
50 284 281 297 290 302 299 280
60 290 301 302 298 283 286 287
100 285 283 297 287 289 282 283
我也包含了您正在尝试的方法。您必须在列上指定 mask
。您在整个数据帧上执行此操作:
import pandas as pd
import numpy as np
# Model 1 data
depthmod1 = [5, 10, 15, 20, 30, 50, 60, 80, 100] #depth in meters
latmod1 = [50, 50.5, 51, 51.5, 52, 52.5, 53] #latitude in degrees north
tmpumod1 = np.random.randint(273,303,size=(len(depthmod1),len(latmod1))) #temperature
dfmod1 = pd.DataFrame(tmpumod1,index=depthmod1,columns=latmod1)
dfmod1
depthmod2 = [5, 10, 15, 25, 35, 50, 60, 100]
latmod2 = [50, 51, 52, 53]
tmpumod2 = np.random.randint(273,303,size=(len(depthmod2), len(latmod2)))
dfmod2 = pd.DataFrame(tmpumod2,index=depthmod2,columns=latmod2)
depthxsect = np.intersect1d(depthmod1, depthmod2)
depthmask = dfmod1.index.isin(depthxsect) == False
for col in dfmod1.columns:
dfmod1[col] = dfmod1[col].mask(depthmask, np.nan)
dfmod1
Out[3]:
50.0 50.5 51.0 51.5 52.0 52.5 53.0
5 289.0 274.0 297.0 274.0 277.0 278.0 277.0
10 282.0 280.0 277.0 302.0 297.0 289.0 278.0
15 300.0 282.0 297.0 297.0 300.0 279.0 291.0
20 NaN NaN NaN NaN NaN NaN NaN
30 NaN NaN NaN NaN NaN NaN NaN
50 285.0 297.0 292.0 301.0 296.0 289.0 291.0
60 295.0 299.0 278.0 295.0 299.0 293.0 277.0
80 NaN NaN NaN NaN NaN NaN NaN
100 292.0 293.0 289.0 291.0 289.0 276.0 286.0