【问题标题】:How to map display sizes to standard sizes in a pandas dataframe column?如何将显示尺寸映射到熊猫数据框列中的标准尺寸?
【发布时间】:2021-01-21 01:38:04
【问题描述】:

我知道标题可能不太清楚,但请听我说完。

我有一个大约 850 种不同显示尺寸的 pandas 数据框列,例如

1   320x480
2   480x320
3   382x215
4   676x320
5   694x320
6   1080x2123
7   2094x1080
8   1080x2020

我想匹配它们/将它们转换为最接近的标准显示尺寸(用例数据集中提供了大约 20 个)。

320x350
320x480
480x320
640x360
800x600
1024x768
1280x720
1280x800
1280x1024
1360x768
1366x768
1440x900
1536x864
1600x900 

我尝试将高度和宽度分成单独的列并将它们四舍五入,但它仍然会创建许多非标准显示尺寸(对于我的用例)。

我怎样才能做到这一点?

【问题讨论】:

    标签: python pandas string dataframe string-matching


    【解决方案1】:

    想法是通过Series.str.split 将两个列/系列都转换为DataFrames,然后通过DataFrame.merge 使用交叉连接,获取差异并对它们求和,通过DataFrameGroupBy.idxminDataFrame.loc 获得差异最小的行,最后加入DataFrame.pop 用于使用和删除列:

    df11 = df1['col'].str.split('x', expand=True).astype(int)
    df22 = df2['col'].str.split('x', expand=True).astype(int)
    
    df = df11.assign(a=1).merge(df22.assign(a=1), on='a')
    df['diff'] = df['0_x'].sub(df['0_y']).abs() + df['1_x'].sub(df['1_y']).abs()
    
    df = df.loc[df.groupby(['0_x','1_x'])['diff'].idxmin()]
    df['a'] = df.pop('0_x').astype(str).str.cat(df.pop('0_y').astype(str), 'x')
    df['b'] = df.pop('1_x').astype(str).str.cat(df.pop('1_y').astype(str), 'x')
    print (df)
                 a  diff          b
    1      320x320     0    480x480
    28     382x320   197    215x350
    16     480x480     0    320x320
    45     676x640    76    320x360
    59     694x640    94    320x360
    106  1080x1280  1196  2020x1024
    78   1080x1280  1299  2123x1024
    97   2094x1600   674   1080x900
    

    与欧几里得距离类似,输出样本数据相同:

    df11 = df1['col'].str.split('x', expand=True).astype(int)
    df22 = df2['col'].str.split('x', expand=True).astype(int)
    
    df = df11.assign(a=1).merge(df22.assign(a=1), on='a')
    df['diff'] = np.sqrt(df['0_x'].sub(df['0_y']) ** 2 + df['1_x'].sub(df['1_y']) ** 2)
    
    df = df.loc[df.groupby(['0_x','1_x'])['diff'].idxmin()]
    df['a'] = df.pop('0_x').astype(str).str.cat(df.pop('0_y').astype(str), 'x')
    df['b'] = df.pop('1_x').astype(str).str.cat(df.pop('1_y').astype(str), 'x')
    print (df)
                 a         diff          b
    1      320x320     0.000000    480x480
    30     382x480   143.627992    215x320
    16     480x480     0.000000    320x320
    45     676x640    53.814496    320x360
    59     694x640    67.201190    320x360
    106  1080x1280  1015.881883  2020x1024
    78   1080x1280  1117.050133  2123x1024
    97   2094x1600   525.771814   1080x900
    

    另一个 numpy 解决方案:

    df11 = df1['col'].str.split('x', expand=True).astype(int)
    df22 = df2['col'].str.split('x', expand=True).astype(int)
    
    a1 = np.sqrt(np.square(df11[0].to_numpy()[:, None] - df22[0].to_numpy()) + 
                 np.square(df11[1].to_numpy()[:, None] - df22[1].to_numpy()))
    
    df1['b1'] = df2['col'].to_numpy()[np.argmin(a1, axis=1)]
    
    
    a2 = (np.abs(df11[0].to_numpy()[:, None] - df22[0].to_numpy()) + 
          np.abs(df11[1].to_numpy()[:, None] - df22[1].to_numpy()))
    
    df1['b2'] = df2['col'].to_numpy()[np.argmin(a2, axis=1)]
    print (df1)
             col         b1         b2
    1    320x480    320x480    320x480
    2    480x320    480x320    480x320
    3    382x215    480x320    320x350
    4    676x320    640x360    640x360
    5    694x320    640x360    640x360
    6  1080x2123  1280x1024  1280x1024
    7  2094x1080   1600x900   1600x900
    8  1080x2020  1280x1024  1280x1024
    

    【讨论】:

    • 谢谢。我认为您的 numpy 解决方案是我正在寻找的最接近的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多