【问题标题】:Python: Issue subsetting rows of pandas dataframe using .isin()Python:使用 .isin() 发出熊猫数据框的子集行
【发布时间】:2020-08-10 19:19:19
【问题描述】:

我有一个 pandas 数据框,其中包含名为“t”和“y”的两列,其中包含浮点数。 't' 列包含从 0 到 200(包括)以 0.1 为增量的数字。我的目标是对 t 为 0 到 200(含)之间的 integer 的数据框的行进行子集化。我这样做的尝试产生了奇怪的结果。你可以从 Github here 找到我使用的数据来重现我的结果。

旁注:我为链接数据道歉,但奇怪的是我无法通过使用 numpy.arange 生成两组任意值来重现我得到的结果(增加了我的困惑......)。

这是我的代码:

import pandas as pd
import numpy as np

data = pd.ExcelFile(r'C:\Users\Leonidas\Documents\sample_data.xlsx')
data = data.parse(sheet_name = "Sheet1")

df = pd.DataFrame(data)
df.columns = ['t','y']
nums = np.arange(0,201)

df2 =  df.loc[df['t'].isin(nums)]

print(df2)

这是我得到的输出:

        t         y 
0     0.0  1.000000
20    2.0  0.999710
30    3.0  0.999576
40    4.0  0.999446
190  19.0  0.997854
200  20.0  0.997768
210  21.0  0.997684
220  22.0  0.997602
230  23.0  0.997521
240  24.0  0.997443
250  25.0  0.997367
740  74.0  0.995241
750  75.0  0.995219

此代码已对 t = 0,2,3,4,19,20,21,...,25,74,75 的行进行了子集化。 (???)我期待有 t = 0,1,2,3,...,200 的行。我很困惑为什么我想要的行中只有少数(似乎是随机的)选择被子集化...任何见解/帮助将不胜感激!

【问题讨论】:

  • isin 仅适用于确切的事件。在您的文件中,t 列中似乎有很多小数,例如 199.999999999992(在 Excel 中显示为 200)
  • 啊,这一定是问题的原因!有没有办法在比较一组值时引入容差? (即子集 t 在 np.arange(0,201) 中某个数字的 10e-4 范围内的所有行?
  • 您可以在检查isin之前将列四舍五入

标签: python pandas dataframe subset rows


【解决方案1】:

正如我在评论中所说,您的数据集 t 列上的值不是精确的整数。我测试了以下代码,似乎四舍五入有效:

import numpy as np
import pandas as pd
df = pd.read_excel("https://github.com/MichaelBarmann/sample-data/raw/master/sample_data.xlsx", "Sheet1")
nums = np.arange(0,201)
df2 = df.loc[df['t'].round(2).isin(nums)]
print(df2['t'].values)

会输出

[  0.   1.   2.   3.   4.   5.   6.   7.   8.   9.  10.  11.  12.  13.
  14.  15.  16.  17.  18.  19.  20.  21.  22.  23.  24.  25.  26.  27.
  28.  29.  30.  31.  32.  33.  34.  35.  36.  37.  38.  39.  40.  41.
  42.  43.  44.  45.  46.  47.  48.  49.  50.  51.  52.  53.  54.  55.
  56.  57.  58.  59.  60.  61.  62.  63.  64.  65.  66.  67.  68.  69.
  70.  71.  72.  73.  74.  75.  76.  77.  78.  79.  80.  81.  82.  83.
  84.  85.  86.  87.  88.  89.  90.  91.  92.  93.  94.  95.  96.  97.
  98.  99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111.
 112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125.
 126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139.
 140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153.
 154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167.
 168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181.
 182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195.
 196. 197. 198. 199. 200.]

【讨论】:

  • 完美,谢谢!这正是我想要的!
【解决方案2】:

如果 t 列由 0.1 个增量组成,您可以简单地选择每 10 列

import pandas as pd
df = pd.DataFrame({'t': [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0], 'y': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]})

df1 = df.iloc[::10, :]

【讨论】:

    【解决方案3】:

    这是一个简单的方法:

    # To reduce the list to integers, use: 
    df[df.t == df.t.astype(int)]
    
    ==>    
            t         S
    0     0.0  1.000000
    20    2.0  0.999710
    30    3.0  0.999576
    40    4.0  0.999446
    190  19.0  0.997854
    200  20.0  0.997768
    210  21.0  0.997684
    ...
    

    要进一步将列表缩减为特定范围内的项目,请使用:

    df[(df.t == df.t.astype(int)) & (df.t >= 0) & (df.t <= 200.0)]
    

    请注意,与浮动比较是棘手的。由于浮点数的限制,例如a + b == c 并不意味着c - b == a。

    【讨论】:

    • 这会产生与我相同的输出,但不是我想要的输出。我想要 t 是 0 到 200 之间的整数的所有行。
    猜你喜欢
    • 2016-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多